알라딘MGG와이드바


UnitTest++ 1.4 Window Project 에 추가하기 개발 이야기

오래간만에 토이 프로젝트에 UnitTest++ 를 추가하려고 보니 까먹은게 많아서 정리차원에서 올립니다.
먼저 UnitTest++ 1.4 를 다운받아서 현재 작업중인 프로젝트에 추가하거나 빌드 후 lib 를 import 합니다.
단위 테스트 결과를 보는 방법은 여러가지가 있습니다만, 저는 콘솔로 보는 걸 선호합니다.
(쑥갓님의 VisualUnitTest++ 를 이용하는 방법도 있지요).
단, Window 프로젝트일 경우에는 따로 콘솔을 붙여줘야 합니다.
자세한 내용은 Adding Console I/O to a Win32 GUI App 를 참고하세요.
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>

using namespace std;

static const WORD MAX_CONSOLE_LINES = 500;

void MyOgreUtil::RedirectIOToConsole()
{
int hConHandle;
long lStdHandle;

CONSOLE_SCREEN_BUFFER_INFO coninfo;

FILE *fp;

// allocate a console for this app
AllocConsole();

// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);

coninfo.dwSize.Y = MAX_CONSOLE_LINES;

SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );

*stdout = *fp;

setvbuf( stdout, NULL, _IONBF, 0 );

// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "r" );

*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );

// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );

*stderr = *fp;

setvbuf( stderr, NULL, _IONBF, 0 );

// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}

그런 후에는, UnitTest::TestReporter 를 상속받아 다음과 같이 만들어 줍니다.
이렇게 하면 콘솔에서도 테스트 결과를 볼 수 있고, 에러가 났을 때 VisualStudio 출력창을 더블클릭하면
에러가 난 소스로 이동할 수 있습니다(자바워크님께 배운 방법입니다.)
class TestReporterVisualC : public TestReporter
{
private:
virtual void ReportTestStart(TestDetails const& /*test*/) {}
virtual void ReportFailure(TestDetails const& details, char const* failure)
{
char buffer[1024] = {0,};
char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n";
sprintf_s(buffer, errorFormat, details.filename, details.lineNumber, details.testName, failure);

OutputDebugString(buffer);
cout << buffer;
}
virtual void ReportTestFinish(TestDetails const& /*test*/, float) {}
virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed)
{
TCHAR buffer[1024] = {0,};
if (failureCount > 0) {
sprintf_s(buffer,
"FAILURE: %d out of %d tests failed (%d failures).\n",
failedTestCount, totalTestCount, failureCount);
} else {
sprintf_s(buffer, "Success: %d tests passed.\n", totalTestCount);
}
OutputDebugString(buffer);
cout << buffer;

sprintf_s(buffer, "Test time: %.2f seconds.\n", secondsElapsed);
OutputDebugString(buffer);
cout << buffer;
}
};

이제 WinMain 앞을 다음과 같이 만들면 끝입니다.
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) {
Util::RedirectIOToConsole();

TestReporterVisualC reporter;
TestRunner runner(reporter);
runner.RunTestsIf(Test::GetTestList(), NULL, True(), 0);

char temp;
std::cin >> temp;

// do someting...

재미있는 것은 Ogre 작업하다가 테스트가 필요해서 콘솔을 붙였는데, 오우거 내부에서 콘솔로 내뱉는 정보가 꽤 있더군요.
생각지도 못한 걸 알게 되었습니다.

참고 :
KGC2007 - 'UnitTest, TDD in Games' 발표 자료
낡은 코드(Legacy Code)로 효율적으로 일하기
측정하지 못하면 관리하지 못한다. 정말?
테스트 주도 개발. 무엇을 어떻게 왜?
실전! 지속적인 통합 7편: 단위 테스트 2편 - UnitTest++ 도입하기 - 최재훈
VisualStudio + UnitTest++에서 abort() 처리하기
레이옷님 : 어떻게 우리 팀의 XP가 실패했는가?
LineReader TDD 동영상

덧글

  • CharSyam 2010/04/24 19:54 # 삭제 답글

    소문에 의하면 클라이언트로 전향하셨다라는 소문이?
    전 서버로 전향을 쿨럭...
  • 박PD 2010/04/24 22:38 #

    인생사 돌고 도는 거...
댓글 입력 영역


Yes24위대한게임의탄생3

위대한 게임의 탄생 3
예스24 | 애드온2