Altruistic Programmer's Blog (KR)

이타주의 프로그래머의 블로그

Archive for December, 2008

Google C++ Mocking Framework

with 2 comments

[옛날 블로그 글입니다. 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으로 즐거운 테스팅 생활 하세요~ ^^

Written by muscly

December 15th, 2008 at 8:39 am

Posted in 프로그래밍

Tagged with , , , ,

Google C++ Testing Framework

with 2 comments

[옛날 블로그 글입니다.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로 즐거운 테스팅 되세요~ ^^

Written by muscly

December 15th, 2008 at 8:25 am

Posted in 프로그래밍

Tagged with , , ,

팝업 사진 뷰어 만들기

with 3 comments

[옛날 블로그 글입니다. 2009.12.06]
[옛날 블로그에 사용하던 스크립트이고, 지금 블로그와는 상관 없습니다 ^^]

블로그에서 사진을 볼 때 여러모로 불편한 점이 많아서 사진을 클릭하면 원본 크기로 보여주는 팝업 뷰어를 넣어봤습니다.  아래 사진 한 번 눌러보세요~ ^^

기본 동작 이해

스크립트가 하는 일은 이렇습니다.

  • 페이지의 모든 img 엘리먼트를 찾아서 onclick 이벤트를 등록합니다.
  • onclick 이벤트가 발생하면 div 엘리먼트를 하나 삽입합니다. 이 div는 원본 이미지를 갖습니다.
  • 원본 이미지 로딩이 끝나면 이미지 크기를 참조해서 브라우저의 한 가운데로 옮깁니다.
  • 원본 이미지가 클릭되면 2에서 추가한 div 엘리먼트를 삭제합니다.

Prototype JavaScript Framework

Rails 어플리케이션은 기본적으로 Prototype 자바스크립트 프레임워크를 포함하고 있어서, Prototype을 사용해서 작업했습니다.  도움말이 잘 되어있어서 쓰기가 편하네요.

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 의 에디터가 안좋은 건가요 -_-;;

Written by muscly

December 6th, 2008 at 7:43 am

Exuberant Ctags

with 4 comments

[엣날 블로그 글입니다.2008.12.1]

ctags라고 C 소스코드의 태그를 만들어주는 유닉스 프로그램이 있습니다. Vim 같은 편집기에서 이를 활용해서 함수가 정의된 곳으로 한 번에 점프한다거나 하는 기능을 구현하고 있는데요, 다양한 프로그래밍 언어에 대응하는 버전이 바로, Exuberant Ctags 입니다.

지원하는 언어

아래와 같이 34개의 프로그래밍 언어를 지원하고 있습니다.

Assembler ASP Awk BASIC
BETA C C++ C#
COBOL Eiffel Erlang Fortran
HTML Java JavaScript Lisp
Lua Make Pascal Perl
PHP PL/SQL Python REXX
Ruby Scheme Shell scripts (Bourne/Korn/Z)
S-Lang SML (Standard ML) Tcl
Vera Verilog Vim YACC

다운로드 / 설치

http://ctags.sourceforge.net 가셔서 받으시면 됩니다. 윈도우즈 사용하시는 분은 바이너리 버전 받으시면 되고, 맥을 포함한 유닉스 계열은 늘 그렇듯이 아래처럼 하시면 됩니다.

cd ctags
./configure
make
sudo make install

Vim의 Rails 플러그인과 사용하기

Rails 플러그인 설치하는 방법을 따라하셨다면, Vim에서 가볍게 아래처럼 써넣어줍니다. (에러가 나면서 ctags 사용법을 알려준다면 내장된 ctags가 실행된 것일 확률이.. 경로 설정등을 확인해주세요~ :)

:!Rtags

이 명령은 현재 소스코드를 기준으로 태깅 파일을 만들어 줍니다. Rails 플러그인이 여러분이 작성중인 어플리케이션의 루트 디렉토리를 자동으로 찾아주니까, 태깅을 할 범위나 태그 파일의 위치 같은 것은 신경쓰지 않아도 됩니다. 아주 편리하지요. ^^

이제 Vim의 태그 관련 커맨드를 사용해서 편하게 소스코드를 돌아다니시면 됩니다. 원하는 심볼 위에서 Ctrl + ] 를 누르시면 정의된 곳으로 점프하고, 다시 Ctrl + T 를 누르면 점프하기 전의 위치로 돌아옵니다. 여러 번 점프한 경우에도 잘 동작하고요.

Vim과 사용하기

요건 굳이 제가 따로 정리 안해도 될만큼 자료가 많아서요. ^^ 구글 검색에 제일 먼저 나오는 링크를 살짝 넣어봤습니다.

Exuberant Ctags로 즐거운 소스 분석 되세요~ ^^

Written by muscly

December 1st, 2008 at 7:01 am

Posted in 프로그래밍

Tagged with , , ,