Google Test 빌드 및 설정

1. gtest 빌드하기

gtest-1.6.0.zip 다운로드 후 적당한 곳에 압축을 푼다.
아래 설명은 D:\gtest-1.6.0 에 위치하고 있다고 가정하고 있다.

이제 *.lib를 만들어내야 하는데 README를 보면 CMake를 이용하기를 권장하고 있다.
cross-platform 하게 makefile 또는 project 파일을 만들어낼 수 있으니 멋지긴 한데, 귀차니즘이 발동하면 D:\gtest-1.6.0\msvc 에 있는 solution 파일들을 그냥 사용해도 된다.

해당 폴더에는 두개의 solution 파일이 있는데, gtest-md.sln은 Microsoft runtime libraries의 DLL versions을 이용하는 반면 gtest.sln은 Microsoft runtime libraries의 static versions을 이용한다.
중요한 것은, gtest를 build 시 내 프로젝트(향후 테스트를 적용할)의 C++ Code Generation setting과 정확히 맞아야 한다는 것이다. (Project 속성 > 구성 속성 > C/C++ > 코드 생성 에서 ‘런타임 라이브러리’ 확인)
나는 보통 static versions of the runtime libraries를 이용하며 /MT 또는 /MTd로 주로 셋팅한다. 즉 gtest.sln을 사용해야 한다.

하지만, 결국 CMake를 이용했는데 상기 방법을 이용시 $(TargetName) 등으로 인한 warning이 발생했기 때문이다. (warning을 아주 싫어한다)
수정해서 진행할까 하다가 그냥 공식적인 방법을 쓰기로 결정했다. (어렵지도 않다)

20120808_gtest_1

상기 화면과 같이 순서대로 처리 후 D:\gtest-1.6.0\lib\gtest.sln을 더블클릭 하여 VS를 연 다음 ‘솔루션 빌드’를 한다. D:\gtest-1.6.0\lib\Debug에 가면 gtest.lib와 gtest_main.lib가 만들어져 있는 것을 볼 수 있다.

2. gtest 내 sample 테스트

gtest-1.6.0\samples 에 보면 멋진 sample들이 있다. 그중 첫번째 sample을 선택해서 VS 내에 구성해보기로 했다.

20120808_gtest_2

먼저 ‘Google Test’란 solution을 만들고 그 안에 Example이란 프로젝트와 ExampleTest란 프로젝트를 구성했다.
최종구현물이 될 프로젝트에 unit test part가 섞여 있으면 너무 복잡해지고 별로 보기도 안 좋기 때문에 Eclipse에서 JUnit 사용할 때 같이 따로 분리를 하였다.
sample1.cc은 Example 내에, sample1_unittest.cc는 ExampleTest에, sample1.h는 양쪽에 모두 지정했다. (소스 보면 알겠지만 두 *.cc가 모두 참조한다)
ExampleTest에 main()이 필요한데 이는 gtest-1.6.0\src\gtest_main.cc를 copy하면 된다. 이 소스 안에 보면 RUN_ALL_TESTS() 매크로가 있는데 이 친구가 모든 테스트를 알아서 다 돌려주기 때문이다.

이제 각 프로젝트의 속성을 변경해야 한다. Example에서는 별로 할 것이 없는 반면, ExampleTest에서는 몇가지 신경 쓸 것들이 있다.

Example에서,

  • 구성 속성 > 일반 내 ‘구성 형식’을 ‘정적 라이브러리(.lib)’로 한다. sample1.cc가 main()을 가지고 있지 않은 library 프로젝트이기 때문이다.
  • 구성 속성 > C/C++ > 코드 생성 내 ‘런타임 라이브러리’가 /MTd 로 되어 있는 지 확인한다. 앞서 gtest를 이 방식으로 빌드했기 때문이다.

ExampleTest에서,

  • 공용 속성 > 프레임워크 및 참조 로 가서 ‘Example’을 추가한다.
  • 구성 속성 > C/C++ > 일반 내 ‘추가 포함 디렉토리’에 D:\gtest-1.6.0\include; 를 추가한다.
  • 구성 속성 > C/C++ > 코드 생성 내 ‘런타임 라이브러리’가 /MTd 로 되어 있는 지 확인한다.
  • 구성 속성 > 링커 > 일반 내 ‘추가 라이브러리 디렉토리’에 D:\gtest-1.6.0\lib\Debug; 를 추가한다.
  • 구성 속성 > 링커 > 입력 내 ‘추가 종속성’에 gtest.lib;gtest_main.lib; 를 추가한다.
  • (옵션 사항) 구성 속성 > 빌드 이벤트 > 빌드 후 이벤트 내 ‘명령줄’에 “$(TargetDir)$(TargetFileName)” 를 입력한다. (겹따옴표를 잊지 말도록) 이렇게 설정하면 빌드 직후 출력창에 테스트가 곧장 실행되는 것을 확인할 수 있다.

빌드 하면 아래와 같이 빌드 직후 unit test가 실행되는 것을 볼 수 있다.

추가로,

  • 빌드 시 exe를 못찾겠다고 불평할 때가 있다. 이 경우, 구성 속성 > 일반 내 ‘출력 디렉토리’를 ‘$(SolutionDir)$(ProjectName)\$(Configuration)\‘로 변경해본다.
  • 출력창에서 보면 더 보기 좋게 출력결과가 나온다. 이를 위해 빌드 직후 Ctrl-F5로 곧장 실행하면 Unit Test 수행 하자마자 곧바로 창이 닫혀버리는 문제가 있다. 이를 위해 gtest_main.cc를 살짝 고쳤다.

결과는 아래와 같다.

20120808_gtest_3

Reference

C++을 자주 쓸 일이 없어 그런지 아직도 이따금 헷갈리는 reference. 몇가지만 적어두자.

  • 호출부가 call-by-value와 똑같다. (이것때문에 call-by-value 함수와 헷갈리기도 한다)
  • 함수 원형이 plusref2(int &a) 식으로 레퍼런스를 받는다. 함수 본체 내에서는 call-by-value로 받은 마냥 전달받은 인수를 사용한다. 예를 들어 구조체를 받으면 -> 로 억세스하는 것이 아니라 . 으로 한다.

아래는 구조체 호출의 예이다.

STL에서 배열의 값을 find를 써서 찾을 때는 다음과 같다.

find의 first, last 인자와 리턴이 같은 타입의 iterator라는 것을 고려하면 배열에 대해 find를 사용할 때 int *prt = find(&a[0], &a[5], 849); 로 했는지 이해가 간다. (&a[0]는 a[0], 즉 첫번째 값의 주소)가

C/C++ Coding Style

늘 C/C++ 코딩 시 갈등 하게 만드는 코딩 스타일. 정말 다양한 스타일이 있는데 그 중 좋아하는 순서대로 몇 가지만 추리면,

TIOBE Programming Community Index

TIOBE Programming Community Index 가기

어떤 Programming Language가 가장 인기있는가를 보여주는 index 입니다.

제가 매일 사용하는 ABAP의 경우 순위가 가장 많이 떨어졌네요. 20위.
얼마전 시작한 Haskell의 순위는 36위. 헐…

하지만 저에겐 언제나 흥미로운 언어인 C++와 Python은 각각 3위와 6위를 차지하고 있네요.
all-time-favorite인 C는 부동의 2위를 차지하고 있고.