Archive for December, 2008
Google C++ Mocking Framework
[옛날 블로그 글입니다. 2008.12.15]
Google에서 며칠전에 Mocking Framework를 공개했네요. 목 오브젝트(Mock Object)는 진짜 오브젝트와 똑같은 인터페이스를 갖는 테스트용의 가짜 오브젝트라고 할 수 있는데요, 요즘의 언어는 실행시간에 메소드를 추가하거나 하는 일이 쉬워서 C++ 개발자는 상상도 못하게 편리한 목 프레임웍이 많은 것 같습니다.
Visual C++에서 gmock 사용하기
Google 사이트에 설명이 잘되어 있어서 길게 설명드릴 건 없고요, 귀찮은 분들을 위해서 Visual C++에서의 간단한 설정 방법과 예제 소스를 보여드리려고 합니다.
gtest 준비하기
현재로서는 gtest가 필요하답니다. gtest를 설명하는 이전의 포스트를 먼저 읽어주세요.
[수정. 2009.11.7 gmock받으시면 안에 gtest가 들어있습니다. ]
gmock은 Visual C++ 8.0 SP1을 써야 한다고 하니, gtest도 VC 2005로 빌드합니다. 또 gmock은 Unicode를 사용하게 설정되어 있는 반면, gtest는 Multibyte를 사용하게 되어 있으니, 나중에 만들 테스트 프로젝트까지 함께 고려해서 통일시켜 주세요.
gmock 준비하기
아래 주소에서 받아서 적당한 곳에 압축을 풉니다.
http://code.google.com/p/googlemock/downloads/list
그 디렉토리 안에 msvc 디렉토리에 gmock.sln 파일이 있으니 Visual Studio에서 열어서 빌드합니다. 그러면 에러가 나지요. ^^;; C++ TR1에 있는 tuple이 필요하기 때문인데요. 아래 주소에서 boost를 받으면 됩니다.
http://www.boost.org/users/download/
boost의 압축을 풀면 버전번호가 붙은 디렉토리가 생기죠. D:\boost_1_37_0 이라고 하면 아래 두 디렉토리를 Visual Studio의 Include 디렉토리로 등록합니다.
- D:\boost_1_37_0
- D:\boost_1_37_0\boost\tr1\tr1
이제 다시 gmock을 빌드하면 msvc/Debug와 msvc/Release 디렉토리에 결과물이 생깁니다.
테스트 프로젝트 준비하기
Visual Studio에서 콘솔 프로젝트를 하나 만드세요. 우선 유니코드 설정을 gtest, gmock에 맞춰주시고, gtest, gmock은 Multithread Dll을 사용하고 있으니 CRT 설정도 잘 맞춰주세요.
지난 번 포스트를 참고해서 gtest 관련 설정을 먼저 해주시고, gmock에 대한 디렉토리 설정을 합니다.
- gmock 소스 코드 안에 include디렉토리를 추가하셔야 되고
- gmock 소스 코드 안에 msvc/Debug/gmock.lib, msvc/Debug/gmock.lib를 라이브러리로 추가하시면 끝 (참고로 Debug, Release 버전 모두 이름이 gmock.lib니까 주의하세요)
기본 골격코드는 아래와 같습니다.
#include <gtest/gtest.h>
#include <gmock/gmock.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
여기까지 실행해보시고, 에러 나면 잘 잡으세요. ㅎㅎ
테스트 코드 작성하기
여러가지 다양한 기능에 대해서는 Google 문서를 봐주세요.
http://code.google.com/p/googlemock/wiki/ForDummies
아래는 테스트용 MockModel 클래스를 사용해서 Controller 클래스를 테스트하는 예제입니다.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using testing::AtLeast;
using testing::Return;
class IModel {
public:
virtual int method1() = 0;
};
class Controller {
public:
Controller(IModel* m) : model(m) {}
int OnCommand1() {
return model->method1() + model->method1();
}
private:
IModel* model;
};
class MockModel : public IModel {
public:
MOCK_METHOD0(method1, int());
};
TEST(ControllerTest, Command1) {
MockModel model;
EXPECT_CALL( model, method1())
.Times(AtLeast(2))
.WillOnce(Return(100))
.WillOnce(Return(200));
Controller controller(&model);
ASSERT_EQ( 300, controller.OnCommand1() );
}
EXPECT_CALL 부분을 보시면 목 오브젝트를 사용하고 있습니다. 말로 풀어보자면 “model객체의 method1메소드는
말이야, 적어도 2번 호출되야 하고, 처음에는 100을 그 다음에는 200을 반환하게 해줘” 정도가 되겠죠. 2번 미만으로
호출되면 테스트가 실패합니다. 또 목 오브젝트의 반환값을 정할 수 있으니 ASSERT_EQ에 보이는 것처럼 테스트하기가
쉬어집니다.
IModel은 메소드가 1개 뿐이지만, 메소드가 많은 경우라면 MockModel 클래스를 코딩하는게 귀찮은 일이죠. 그래서 코드를 자동으로 생성하는 스크립트도 있다고 하니 Google 문서를 읽어보세요.
위 코드의 결과는 이렇습니다.
마무리
Ruby나 Java 진영의 동적인 목 프레임웍을 보면서 많이 부러워했었는데요. Google에서 마법을 부리지 않고 C++스러운 프레임웍을 편리하게 만들어준 것을 보니, 아직 배울게 많다는 생각이 듭니다. 여러분도 gtest와 gmock으로 즐거운 테스팅 생활 하세요~ ^^
Google C++ Testing Framework
[옛날 블로그 글입니다.2008.12.15]
올해 중순에 Google에서 C++용 테스트 프레임웍을 발표했었네요. 충분히 써보지는 못했지만, 매뉴얼 읽어보고 예제를 만들어본 소감으로는 C++용 테스트 프레임웍 중에서는 최고일 것 같습니다.
전통적인 CppUnit에 비해서 사용법이 상당이 간단합니다. 스크립트 언어를 통해서 테스트 작성을 쉽게 해주는 CxxTest에 비해서도 불편함이 없습니다. 오히려 CxxTest는 개발환경 설정하려면 make파일도 손대야해서 윈도우즈 개발자에게는 대략 난감했었구요.
또 다음 포스팅에서 설명드리려는 Google C++ Mocking Framework까지 함께 사용하면 C++ 개발자도 프레임웍 때문에 유닛테스트 만들기 힘들다는 말은 못하겠네요 -_-;;
Visual C++에서 gtest 사용하기
Google 문서가 워낙 잘 되어 있어서, 설명할 것은 많이 없고요. 귀찮으신 분들을 위해서 간단한 설정과 예제 소스 보여드리려고 합니다.
gtest 준비하기
아래 주소에서 소스 코드를 다운로드 받으시고, 압축 풀어서 적당한 곳에 둡니다.
http://code.google.com/p/googletest/downloads/list
그 안에 보시면 msvc 디렉토리가 있고, 그 안에 gtest.sln 파일을 Visual Studio에서 열어서 빌드하세요. ( 참고로 VC 7.1용 솔루션 파일입니다. ) 빌드가 끝나면 msvc/Debug, msvc/Release 디렉토리에 결과물이 생깁니다.
일단 준비는 여기까지 끝!
테스트 프로젝트 준비하기
Visual Studio에서 콘솔 어플리케이션 하나 만드시고, gtest에 대한 디렉토리 설정을 합니다.
- gtest 소스 코드 안에 include 디렉토리를 추가하셔야 되고
- gtest 소스 코드 안에 msvc/Debug/gtestd.lib, msvc/Release/gtest.lib를 라이브러리로 추가하시면 끝.
기본적인 골격코드는 아래와 같습니다.
#include <gtest/gtest.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
여기까지만 실행해보셔도 좋습니다. 에러 나면 잘 잡으시구요 ㅎㅎ
테스트 코드 작성하기
테스트 코드를 그루핑하는 방법이나 다양한 Assert/Expect 방식에 대해서는 Google 문서를 봐주세요.
http://code.google.com/p/googletest/wiki/GoogleTestPrimer
아래는 간단한 예제와 그 결과입니다.
class StringTest : public testing::Test {
protected:
virtual void SetUp() {
s1 = “Muscly”;
s2 = “Blog”;
}
std::string s1;
std::string s2;
};
TEST_F(StringTest, Equal) {
ASSERT_EQ( s1, s2 );
}
TEST(VectorTest, Size) {
std::vector<int> v;
ASSERT_EQ(0, (int)v.size());
}
마무리
그동안 C++ 개발자는 Java나 C# 개발자에 비해서 손해를 봐왔다는 생각이 듭니다. 최신 개발 기법의 혜택을 보는 것은 Java 진영이 먼저였고, 닷넷 진영은 손쉽게 따라할 수 있었지만, C++ 진영은 언어의 한계로 쉽게 따라 할 수 없었죠. Microsoft도 닷넷에 힘쓰고 있는 상황에 Google이 C++ 개발자를 신경써주니 눈물이 납니다. ^^;;
C++ 개발을 하는 회사라면 표준 프레임웍으로서 권장하고 싶습니다. gtest로 즐거운 테스팅 되세요~ ^^
팝업 사진 뷰어 만들기
[옛날 블로그 글입니다. 2009.12.06]
[옛날 블로그에 사용하던 스크립트이고, 지금 블로그와는 상관 없습니다 ^^]
기본 동작 이해
스크립트가 하는 일은 이렇습니다.
- 페이지의 모든 img 엘리먼트를 찾아서 onclick 이벤트를 등록합니다.
- onclick 이벤트가 발생하면 div 엘리먼트를 하나 삽입합니다. 이 div는 원본 이미지를 갖습니다.
- 원본 이미지 로딩이 끝나면 이미지 크기를 참조해서 브라우저의 한 가운데로 옮깁니다.
- 원본 이미지가 클릭되면 2에서 추가한 div 엘리먼트를 삭제합니다.
Prototype JavaScript Framework
Rails 어플리케이션은 기본적으로 Prototype 자바스크립트 프레임워크를 포함하고 있어서, Prototype을 사용해서 작업했습니다. 도움말이 잘 되어있어서 쓰기가 편하네요.
Prototype JavaScript Framework Homepagehttp://www.prototypejs.org/
img 엘리먼트 찾아서 이벤트 추가하기
var imgs = $$(“#content img”);
var i = 0;
for ( i = 0; i < imgs.length; ++i) {
imgs[i].observe(‘click’, onclick);
imgs[i].setStyle( { cursor: “pointer” } );
}
$$는 CSS 셀렉터에 해당하는 엘리먼트의 배열을 반환해줍니다. observe로 click 이벤트의 핸들러를 추가했구요. 덤으로 커서 스타일도 바꿔줬지요. 누르면 뭔가 일어날 것 같은 느낌을 줘야하니까요 ㅎㅎ
onclick 이벤트 핸들러
function onclick(event) {
var img = Event.element(event);
popupDiv( img.src );
}
Prototype에서 사용하는 이벤트 핸들러 형식인가 봅니다. 어쨌든 이벤트 소스인 img 엘리먼트의 src, 즉 원본 이미지의 URL을 popupDiv() 메소드로 넘기고 있습니다.
div 엘리먼트 삽입하기
function popupDiv(img) {
if ( $(“nb_photoPopup”) )
$(“nb_photoPopup”).remove();
$(document.body).insert(
‘<div id=”nb_photoPopup” style=”position:absolute; top:-9999px;”>’ +
‘<img src=”‘ + img + ‘” onload=”nb_centerPopup();” onclick=”nb_closePopup();” ‘ +
‘ style=”cursor: pointer;” />’ +
‘</div>’ )
}
$는 해당 id를 갖는 엘리먼트를 반환합니다. 팝업이 이미 있다면 remove() 메소드로 없애주는 코드가 있고요. 아래쪽 코드 뭉터기는 body에 새 div를 삽입하고 있습니다. 위치를 -9999px로 해서 안보이게 해뒀지요. display: none; 처럼 정말로 안보이게 하면 나중에 크기를 알아내는게 어려워지더라고요.
제가 좀 알아보니까 이미지가 로딩되기 전에는 원본 크기를 알 수가 없는 것 같아서요. img가 로딩되면 nb_centerPopup() 메소드를 호출하도록 했습니다.
그리고 img 엘리먼트의 커서 모양도 바꿔줬습니다. 누르면 닫힐 것 같은 느낌을 줘야하니까요. ^^
화면 한 가운데로 보여주기
function nb_centerPopup() {
// Calculate new position
var photoDim = $(“nb_photoPopup”).getDimensions();
var viewportDim = document.viewport.getDimensions();
var viewportPos = document.viewport.getScrollOffsets();
var viewportCenter = {
top: viewportPos.top + viewportDim.height / 2,
left: viewportPos.left + viewportDim.width / 2 };
var photoPos = {
top: viewportCenter.top – photoDim.height / 2,
left: viewportCenter.left – photoDim.width / 2 };
// move!
$(“nb_photoPopup”).setStyle( {
top: photoPos.top + “px”,
left: photoPos.left + “px” });
}
코드가 좀 길지만, 위에 한 뭉터기는 팝업 뷰어 div의 위치를 계산하고 있고요. 아래 한 뭉터기는 div의 위치를 옮기고 있습니다.
계산을 할 때는 img 엘리먼트의 크기가 아니라 부모인 div의 크기로 계산을 하는게 중요합니다. div가 테두리를 만드려고 padding을 가지고 있을 수도 있으니까요.
팝업을 누르면 사라지기
function nb_closePopup() {
if ( $(“nb_photoPopup”) )
$(“nb_photoPopup”).remove();
}
앞에서 img가 눌리면 nb_closePopup()이 호출되게 해두었습니다. div 엘리먼트를 삽입하는 코드를 보시면 있어요. 뭐, 간단히 remove() 메소드로 없애주면 끝입니다.
CSS로 테두리 만들기
#nb_photoPopup {
background-color: gray;
padding: 20px;
}
멋있는 사진틀을 만들 수 있으면 좋겠지만 가정이 있는 사람은 집에서 코딩할 시간이 많지 않으니까요. -_-;; 이렇게 회색 테두리를 넣으면 끝~ 입니다!
스크립트 시작하기
window.onload = function() {
nb_installPhotoViewer();
}
스크립트 설명은 아니고, 페이지가 로딩이 다 되었을때 img 엘리먼트에 이벤트를 추가해야 되니까요. 이렇게 하시라고 알려드리는 차원에서 보여드리는 코드입니다. nb_installPhotoView() 함수 안에 맨 처음에 보여드린 코드가 들어있다고 생각하시면 되겠죠. ^^
마무리
지난 밤에 심심해서 만들어 본 것이 의외로 쉽게 끝나서 기분이 좋네요. 자바스크립트는 참 괜찮은 프로그래밍 언어라는 생각도 좀 들고, 개발자가 좀 고생하면 여러 사용자가 행복진다는 생각도 좀 듭니다.
나중에 시간이 되면 사진틀도 좀 멋있게 디자인해보고 애니메이션도 넣어봐야겠습니다. 사진 뷰어도 추가됐으니 블로그에 사진도 한 번씩 더 봐주세요~ ^^
p.s. 웹에서 글 편집하는게 너무 힘드네요. YUI 의 에디터가 안좋은 건가요 -_-;;
Exuberant Ctags
[엣날 블로그 글입니다.2008.12.1]
ctags라고 C 소스코드의 태그를 만들어주는 유닉스 프로그램이 있습니다. Vim 같은 편집기에서 이를 활용해서 함수가 정의된 곳으로 한 번에 점프한다거나 하는 기능을 구현하고 있는데요, 다양한 프로그래밍 언어에 대응하는 버전이 바로, Exuberant Ctags 입니다.
지원하는 언어
아래와 같이 34개의 프로그래밍 언어를 지원하고 있습니다.
다운로드 / 설치
http://ctags.sourceforge.net 가셔서 받으시면 됩니다. 윈도우즈 사용하시는 분은 바이너리 버전 받으시면 되고, 맥을 포함한 유닉스 계열은 늘 그렇듯이 아래처럼 하시면 됩니다.
Vim의 Rails 플러그인과 사용하기
Rails 플러그인 설치하는 방법을 따라하셨다면, Vim에서 가볍게 아래처럼 써넣어줍니다. (에러가 나면서 ctags 사용법을 알려준다면 내장된 ctags가 실행된 것일 확률이.. 경로 설정등을 확인해주세요~
:!Rtags
이 명령은 현재 소스코드를 기준으로 태깅 파일을 만들어 줍니다. Rails 플러그인이 여러분이 작성중인 어플리케이션의 루트 디렉토리를 자동으로 찾아주니까, 태깅을 할 범위나 태그 파일의 위치 같은 것은 신경쓰지 않아도 됩니다. 아주 편리하지요. ^^
이제 Vim의 태그 관련 커맨드를 사용해서 편하게 소스코드를 돌아다니시면 됩니다. 원하는 심볼 위에서 Ctrl + ] 를 누르시면 정의된 곳으로 점프하고, 다시 Ctrl + T 를 누르면 점프하기 전의 위치로 돌아옵니다. 여러 번 점프한 경우에도 잘 동작하고요.
Vim과 사용하기
요건 굳이 제가 따로 정리 안해도 될만큼 자료가 많아서요. ^^ 구글 검색에 제일 먼저 나오는 링크를 살짝 넣어봤습니다.
Exuberant Ctags로 즐거운 소스 분석 되세요~ ^^


