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으로 즐거운 테스팅 생활 하세요~ ^^

무플 방지.ㅎㅎ
항상 느끼는 거지만 개발 관련 포스팅엔 덧글이 적다는 -_-;
승철
29 Dec 08 at 2:13 am
무플 방지 위원회 회장으로 임명!!
muscly
3 Jan 09 at 4:26 am