기본적으로 cppUnit 에서 쓰이는 main 함수는 Text 모드 일때는 동일합니다. 각각의 세부 정보까지 표시하게 만든 버젼입니다. 다음부터 cppUnit Test Project 를 작성할때는 이부분을 복사해서 main 부분을 구성하면 똑같게 사용이 가능합니다.

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>


int main (int argc, char * argv[])
{
    CPPUNIT_NS::TestResult controller ;
    CPPUNIT_NS::TestResultCollector result ;


    controller.addListener(&result);


    CPPUNIT_NS::BriefTestProgressListener progress ;
    controller.addListener(&progress);

    CPPUNIT_NS::TextUi::TestRunner runner;
    runner.addTest
( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()); try { runner.run( controller ); CPPUNIT_NS::stdCOut() << "\n"; // Print test in a compiler compatible format. CPPUNIT_NS::CompilerOutputter outputter( &result
,
CPPUNIT_NS::stdCOut() ); outputter.write(); // Uncomment this for XML output // std::ofstream file( "tests.xml" ); // CPPUNIT_NS::XmlOutputter xml( &result, file ); // xml.setStyleSheet( "report.xsl" ); // xml.write(); // file.close(); } catch ( std::invalid_argument &e ) / Test path not resolved { CPPUNIT_NS::stdCOut() << "\n" << "ERROR: " << e.what() << "\n"; return 0; } return result.wasSuccessful() ? 0:1 ; }

결과 입니다.

testbadc.exe
CalculateTest::testLoad : OK
CalculateTest::testDisplayData : assertion
c:\crazia\work\testbadc\calculatetest.h(32) : error : Assertion
Test name: CalculateTest::testDisplayData
assertion failed
- Expression: pr.open(_T("TSS_TEST_pr_2.tot"))
Failures !!!
Run: 2   Failure total: 1   Failures: 1   Errors: 0

드디어 대망의 cppUnit 과 CruiseControl.NET 과의 결합입니다. 일단은 개념만 다루기로 하고 다음 포스트에서 프로젝트를 하나 하나 생성해 나가면서, SVN , CI , Schedule , TDD , IssueTracker 까지 적용해서 하나의 프로젝트로 만드는 포스팅 할 예정입니다. (우리 회사에서 적용하고 있는 방법론이기도 합니다, 비용은 인건비만 들고 실용주의 시스템 구성에 돈이 안드는 방법론을 맛볼 수 있습니다.) 저는 맘대로 그 방법을 도입한 형태를 실천주의 구성이라고 합니다 ㅎㅎ

지금까지 cppTest 프로젝트를 하면서 , 화면에 (콘솔) 테스트 결과가 출력되는 형태까지 봐 왔을것입니다. 이제부터 CruiseControl.NET 의 웹 대쉬보드 에 테스트 결과를 출력하게 해서 CI 에 적용되는 프로젝트에 자동화 테스트 까지 추가하기로 하겠습니다.

현재 프로젝트의 환경을 보기로 하지요. (기존의 프로젝트를 CI 에 관리하에 뒀다는 가정하에 진행하겠습니다.)

프로젝트명 : cppTest 
프로젝트위치: d:\user\crazia\cppTest
실행파일위치: d:\user\crazia\cppTest\debug\cppTest.exe


자세한것은 저번 포스트에서 다루고 있습니다. (좀 연재한것이 많아서 링크는 못했습니다.)

처음으로 해야 할 일은 cppTest 프로젝트가 xml 파일을 output으로 내게 하는 일입니다.
역시 cppTest.cpp 파일을 수정해 줍니다.

#include "stdafx.h"
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>

#include <fstream>

int _tmain(int argc, _TCHAR* argv[])
{
  CPPUNIT_NS::TestResult controller ;

  CPPUNIT_NS::TestResultCollector result ;
  controller.addListener (&result);

  CPPUNIT_NS::TestRunner runner ;
  runner.addTest(
CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()); runner.run(controller); std::ofstream file("Results.xml"); CPPUNIT_NS::XmlOutputter xml(&result , file); xml.setStyleSheet("report.xsl"); xml.write(); file.close(); return result.wasSuccessful() ? 0: 1;
}



기존 소스와 다른점은 아래쪽에 추가된 부분이라고 할 수 있겠습니다.
Results.xml 을 지정해서 그 파일을 XmlOutPutter 의 결과로 지정해주는 부분입니다.
이렇게 되면 테스트의 상세 결과가 Results.xml 로 저장이 됩니다. stylesheet 를 지정해주는 부분은 옵션입니다. 만약 스타일 쉬트를 지정하게 되면 output 폴더에 꼭 reports.xsl 을 가지고 다녀야 합니다.

자 이제 Test 프로젝트를 준비가 됐으니 다음은 ccnet.config 를 손볼
차례입니다. 이 파일은 보통 %CRUISECONTROL.NET%\server 에 있습니다.
기존의 <devenv> 태그 다음에 다음과 같은 내용을 추가합니다.

   <exec>
        <executable>cppTest.exe</executable>
        <baseDirectory>D:\User\Crazia\Work\cppTest\debug</baseDirectory>
        <buildTimeoutSeconds>10</buildTimeoutSeconds>
    </exec>

위 내용은 프로젝트를 빌드후에 실행해줘야 하는 것을 지정해준
것입니다. 위의 프로그램 예제에서 보여줬듯이 이 방법을 써서 테스트
프로젝트를 실행하면 Results.xml 에 테스트 결과가 저장됩니다. 이 결과를
기존의 빌드로그 가 표시되는 xml 파일에 병합해야 하는 문제가
남았습니다. <task> 태그가 닫히고 난 뒤 같은 레벨에 존재하는 <publishers>
태그가 그 부분을 처리해 줍니다. 정확히는 <merge> 태그 안에 병합할
파일을 써주시면 됩니다. 다음에 그 예제를 적어 뒀습니다.

  <task>
    ...
    <devenv>
      ..
    </devenv>
    <exec>
        <executable>cppTest.exe</executable>
        <baseDirectory>D:\User\Crazia\Work\cppTest\debug</baseDirectory>
        <buildTimeoutSeconds>10</buildTimeoutSeconds>
    </exec>
  </tasks>
  <publishers>
    <merge>
      <files>
        <file>D:\User\Crazia\Work\cppTest\debug\Results.xml</file>
      </files>
    </merge>
    <xmllogger  />
  </publishers>

마지막으로 실제 build report 부분에서 테스트 결과를 볼 수 있게 하는
방법에 대해서 알아보도록 하지요.

이 부분은 이부분 을 참조했습니다. 이 CruiseControl.NET web dashboard 는 빌드
로그를 xsl 파일을 통해서 값을 파싱해서 그 결과값을 화면에
뿌려줍니다. 그래서 기존의 xsl 파일로는 cppUnit 이 만들어 내는 결과를
인식 못합니다. (위에 써둔 Results.xml 을 빌드로그에 병합한 형태를 인식
못함)

따라서 unittest.xsl 를 다운 받아서 %CRUISECONTROL.NET%\webdashboard\xsl
에 넣어줍니다.


사용자 삽입 이미지

위 사진은 모든것이 설정되고 난뒤 빌드 리포트에 생긴 테스트 결과 입니다.

지금까지 cppUnit 과 CruiseControl.NET 과 결합에 대해서 알아보았습니다. 사실 CruiseContorl.NET은 .net 용이기 때문에 cpp 에 관해서는 따로 지원하는 부분이 없습니다. 항상 없는 부분을 만들어 내는 그 부분이 귀찮고 힘들기 때문에 많은 사람들이 포기하기도 합니다. devenv 자체에 포함된 TestProject를 만들 수도 있지만 이것을 사용하면 TDD로 개발이 힘든 부분이 있으며 또한 Test Project 는 XUnit 이 아니라는 점도 마음에 걸려 , 결국 이런 방법을 쓰게 되더군요. 이것때문에 한 일주일간 남는 시간 틈틈이 작업을 한 것 같습니다. ^^; 편하게 할 수 있는 방법들을 찾아서 하세요.
지금까지 CookBook 의 예제를 따라서 하시다 보면 드는 의문이 있을 것입니다. 원칙대로 따라서 소스코드를 친 다음에 나온 결과물을 실행하면

.
OK


라고 덜렁 나오는 것을 볼 수가 있을것입니다. NUnit 을 써보신 분들은 그 화려한 GUI 나 , TextMode 일때에도 나오는 그 많은 정보들이 하나도 나오지 않습니다. 심지어는 내가 무엇을 테스트 하는지에 대한 정보조차 없습니다.  CppUnit 상당히 실망스러울 수밖에 없었습니다. 하지만 없을리가 없지 않습니까 ㅎㅎ , 그래서 조금 조사해보니 답이 나오더군요.

cppTest.cpp 만 바꿔 주면 됩니다.

int main(int argc , char **argv)
{

 // 결과값을 저장하기 위한 매니저와 콘트롤러 성격을 선언해줍니다.
  CPPUNIT_NS::TestResult controller;


  // 결과값을 저장하기 위한 컬렉터를 추가해줍니다.
  CPPUNIT_NS::TestResultCollector result;
  controller.addListener( &result );


  // 테스트가 진행되는 동안 "." 을 표시해서 진행시간 추정하게 해주는
  // 프로그래스 부분을 추가합니다.
  CPPUNIT_NS::BriefTestProgressListener progress;
  controller.addListener( &progress );


  // 기존과 동일하게 테스트 러너를 돌려줍니다.

  CPPUNIT_NS::TextUi::TestRunner runner;
  runner.addTest(  CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()  );
  runner.run( controller );

  return result.wasSuccessful() ? 0 : 1 ;
}

쉽지요? 기존의  코드랑 다른점은 또 있습니다. CppUnit 대신 CPPUNIT_NS 가 쓰이지요? 그게 강조사항이더군요. 그래서 적용해줬습니다.  이렇게 바꾸고 실행해보세요 결과는 직접 확인하시고요.

참 추가해야 할 헤더 파일 들 입니다.

#include <cppunit/TestResultCollector.h>
#include <cppunit/BriefTestProgressListener.h>

추가 해야지만 컴파일 됩니다.

Suite

테스트 케이스를 한꺼번에 몰아서 돌릴려고 하면 , Suite 가 필요합니다. 정확히는 TestSuite 이지요. 전 포스팅에서 한개체를 돌리는 경우를 봤으니 이번에는 한번에 돌리는걸 알아 보도록 하죠.

cppTest.cpp

#include <cppunit/TestSuite.h>

int _tmain(int argc, _TCHAR* argv[])
{

    CppUnit::TestSuite suite;
    CppUnit::TestResult result;
     suite.addTest( new CppUnit::TestCaller<ComplexNumberTest>(
                       "testEquality",
                       &ComplexNumberTest::testEquality ) );
      suite.addTest( new CppUnit::TestCaller<ComplexNumberTest>(
                       "testAddition",
                       &ComplexNumberTest::testAddition ) );
       suite.run( &result );

     return 0;
}


main 을 위와 같이 변경합니다. TestSuite 를 한개 선언하고 suite 에 한개씩 TestCaller 를 이용해서 test 메서드를 채워 넣고 한꺼번에 호출하는 형식입니다. 위 예제에서는 testEquality , testAddtion 을 추가하고 있습니다.

이 뿐만 아니라 미리 만들어둔 suite 가 있다면 새로운 suite 에 병합을 시킬 수도 있습니다.

CppUnit::TestSuite suite;
CppUnit::TestResult result;
suite.addTest( ComplexNumberTest::suite() );
suite.addTest( SurrealNumberTest::suite() );
suite.run( &result );

suite 는 Test 기반 Interface 를 가진 것들은 전부 포함시킬 수가 있습니다.

TestRunner

드디어 TestRunner 까지 왔습니다. 지금까지의 TestCase 들은 동작하면 아무런 문제 없이 프로그램이 종료됐고, 문제가 발생했다면( Test 가 실패했다면 ) 프로그램이 종료됐습니다. 조금 답답한 인터페이스 이지요. Test 를 하고 그 결과를 보고 싶을때는 어떻게 하는가에 대한 대답이 TestRunner 입니다.

TestRunner 도 Test Interface 를 가진 Test 들을 (Suite 나 TestCase ) 추가로 포함해서 실행하고 그 결과를 보여 줄 수 있습니다.

다만 TestRunner 에게 연결이 될려면 CppUnit::Test * 형식을 반환하는 static 함수가 포함되어야 합니다.

complextest.h

void testAddition()
  {
    CPPUNIT_ASSERT( *m_10_1 + *m_1_1 == *m_11_2 );
  }

 static CppUnit::Test *suite()
  {
    CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite( "ComplexNumberTest" );
    suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
                                   "testEquality",
                                   &ComplexNumberTest::testEquality ) );
    suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
                                   "testAddition",
                                   &ComplexNumberTest::testAddition ) );
    return suiteOfTests;
  }


기존의 code 중 testAddtion 함수 밑에 붉은 색 부분을 추가합니다.
그리고 main 함수를 바꿉니다.

cppTest.cpp 

#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TestResult.h>


int _tmain(int argc, _TCHAR* argv[])
{

  CppUnit::TextUi::TestRunner runner;
  runner.addTest( ComplexNumberTest::suite() );
  runner.run();

  return 0;
}


일단 추가한 헤더파일은 TestRunner 의 헤더 파일입니다. cppunit 기본으로 Text 버젼이 포함되어 있습니다. MFC 버젼이나 QT , QT4 버젼을 쓰고 싶으신 분은 관련 자료를 쉽게 찾으실 수가 있습니다. - 관련 URL 링크 해뒀음

TestRunner 는 테스트를 실행하고 정보를 저장합니다. 성공하면 - 성공했다는 메시지와 함께 실패하면

 - 실패한 테스트 케이스 이름
 - 테스트를 포함한 소스 파일의 이름
 - 실패가 일어난 줄 번호
 - 실패를 야기한 곳의 모든 Text 정보입니다. ( 애매해서 의역이 심하네요 ㅎㅎ)



 

그냥 컴파일 하면 에러가 발생합니다.

> g++ -o test test.cpp -lcppunit
> ./libcppunit.so: undefined reference to `dlclose'
> ./libcppunit.so: undefined reference to `dlopen'
> ./libcppunit.so: undefined reference to `dlsym'
> collect2: ld returned 1 exit status
> make: *** [test] Error 1



이런 에러 인데 , 기존의 윈도우 체제랑은 달라서 조금 당황합니다. 침착하게 -ldl 옵션을 link 옴션에서 추가해 주시면 무리 없이 컴파일 됩니다.
Fixture 는 Test Case 들을 모아놓구 한꺼번에 실행 시킬때 편리하게 쓸 수 있는 클래스 입니다. 여러 XUnit 프레임 워크를 찾아보시면 Fixture 는 대게 setUp()tearDown() 두가지 메서드를 지원한다는 것을 아실 수 있을 것입니다.

즉 다시 설명하자면, 여러개의 테스트 메서드에서 공통적으로 필요한 준비물이 있다면 (예를 들자면 DB에 접속 한다던지 , 아니면 아래 예제의 경우처럼 복소수 여러개를 미리 준비한다 던지) 이렇게 '미리' 준비하는 부분이 setUp() 메서드 이고, setUp() 에서 설정한 내용을 해제 한다던지 메모리를 지운다던지 DB 접속을 끊는다던지 하는 마무리 작업을 해주는 곳을 tearDown() 이라고 합니다. - 쉽게 말하자면 constructor / destructorinitialize / finalize 를 생각하시면 쉽습니다.

실제로 보기로 하지요.

complextest.h 의 내용
class ComplexNumberTest : public CppUnit::TestFixture {
private:
  Complex *m_10_1, *m_1_1, *m_11_2;
public:
  void setUp()
  {
    m_10_1 = new Complex( 10, 1 );
    m_1_1 = new Complex( 1, 1 );
    m_11_2 = new Complex( 11, 2 ); 
  }

  void tearDown()
  {
    delete m_10_1;
    delete m_1_1;
    delete m_11_2;
  }
};

 setUp() 함수에서 복소수 세개를 생성하고 , tearDown() 에서 그것을 삭제하는 예를 보여줍니다. 이제 여기에 테스트 함수들을 추가해야 겠지요?

추가한 모습입니다.
complextest.h
class ComplexNumberTest : public CppUnit::TestFixture  {
private:
  Complex *m_10_1, *m_1_1, *m_11_2;
public:
  void setUp()
  {
    m_10_1 = new Complex( 10, 1 );
    m_1_1 = new Complex( 1, 1 );
    m_11_2 = new Complex( 11, 2 );
  }
  void tearDown()
  {
    delete m_10_1;
    delete m_1_1;
    delete m_11_2;
  }
  void testEquality()
  {
    CPPUNIT_ASSERT( *m_10_1 == *m_10_1 );
    CPPUNIT_ASSERT( !(*m_10_1 == *m_11_2) );
  }
  void testAddition()
  {
    CPPUNIT_ASSERT( *m_10_1 + *m_1_1 == *m_11_2 );
  }
};
testEquality 와 testAddition 이 추가 됐습니다.

testAddition 을 통과 시킬려면 + Overloading 이 필요합니다.
 
class Complex {
  friend bool operator ==(const Complex& a, const Complex& b);
  double real, imaginary;
public:
  Complex( double r, double i = 0 )
    : real(r)
        , imaginary(i)
  {
  }

  Complex operator+(const Complex& a)
  {
    return Complex(real + a.real , imaginary + a.imaginary);
  }
};

bool operator ==( const Complex &a, const Complex &b )
{
  return a.real == b.real  &&  a.imaginary == b.imaginary;
}





이제 이렇게 되면 호출하는 방법이 조금 까다로운데 , TestFixture 중에서 하나의 테스트 메서드를 호출 하는 형식입니다.

#include <cppunit/TestCaller.h>
#include <cppunit/TestResult.h>
int _tmain(int argc, _TCHAR* argv[])
{
 
  CppUnit::TestCaller<ComplexNumberTest> test( "testEquality",
      &ComplexNumberTest::testEquality );
  CppUnit::TestResult result;
  test.run( &result );

  return 0;
}
저 위의 두 헤더를 추가하시고 , main 이 바뀐 모습처럼 호출해주시면 testEquality 함수를 호출하는 것입니다.

사실 이런 방법이 실제로는 잘 쓰이지 않습니다. TestRunner 에 결과를 위임해서 실패된거랑 성공된 것이랑 통계를 뽑아 내는 식이 많이 쓰이지요. 그래서 다음에는 test함수들을 등록시켜서 내가 원하는 함수들로 테스트를 쭉 뽑아내게 할 수 있는 suite 개념과 TestRunner 부분을 다뤄볼까 합니다.

ps. 참고로 저는 사용자 커스터마이징 INCLUDE , LIB 을 쓰는 것을 별로 좋아하지 않아서 include 파일들은 VC/include/cppunit 밑에 전부 두고, LIB 을 VC/lib 에 둡니다. 그리고 실행 dll 들은 WINDOWS/system32 밑에 둬서 간편한게 빌드하는 방법을 애용합니다. 이건 취향의 문제니 알아서들 원하시는 대로 하시면 됩니다.
CppUnit 을 공부하는 와중에 요리책 (Cookbook)을 따라하면서 한글로 좀 정리를 할 필요가 있어서 정리중입니다. 원래 글은 CookBook 을 직접 보시면 되시고 저는 저의 입장이 많이 반영된 글입니다.

환경 : .NET 2005 의 VC8.0

간단한 테스트 케이스 - Simple Test Case

지금부터 복소수(complex) Class 를 만들어 볼까 합니다. 이를 TDD (Test Driven Development)를 이용해서 작성할 것입니다.

처음에 프로젝트를 생성합니다. 일단 GUI 버젼을 빼고 Text 버젼으로 시작해보지요.

VS2005 에서
파일 - 새로만들기 - 프로젝트  를 선택하시고
Visual C++ 섹션 - Win32 - Win32 콘손 응용 프로그램
으로 새 콘솔용 프로젝트를 생성합니다.

프로젝트 이름은 간단하게 cppTest 라고 합니다.

Test First !! 를 주장하는 TDD 철칙에 따라서 Test Code 부터 주절 주절 작성합니다.

(컴파일도 안되는) Test Code 부터 작성한다.

complextest.h , 와 complextest.cpp 를 생성합니다.

complextest.h - (이거 색깔별로 이쁘게 하는 법이 있던대.. )
#pragma once
class ComplexNumberTest : public CppUnit::TestCase
{
 public:
 ComplexNumberTest( std::string name ) : CppUnit::TestCase (name ) {}
  void runTest ()
  {
    CPPUNIT_ASSERT ( Complex (10, 1) == Complex (10, 1));
    CPPUNIT_ASSERT ( !(Complex(1, 1) == Complex (2, 2)));
  }
};

complexest.cpp
#include "stdafx.h"
#include "complextest.h"

runTest 부분을 보시면 단지 복소수(complex) 가 제대로 생성되서 객체끼리 같은지 비교를 하고 또 다른지 판단을 하는것이 첫 순서라고 할 수 있겠습니다. 그래서 그부분을 테스트 하는 코드를 집어 넣었습니다.

여기서의 CPPUNIT_ASSERT 는 기존의 단언문(ASSERT ) 과 행동하는 것이 똑같습니다. (참이 아니면 프로그램이 살포시 죽어줍니다. )

이제 테스트 Class 를 생성해 주었으니 , 이를 메인에서 호출하게 해 줘야 겠지요.

cppTest.cpp
#include "stdafx.h"
#include "complextest.h"
int _tmain(int argc, _TCHAR* argv[])
{
  ComplexNumberTest test("test") ;
  test.runTest();
        return 0;
}
 

붉은색이 제가 추가한 부분입니다.
자 이제 테스트 코드를 작성했으니 Build 를 해 줄 차례지요? IDE 에서 F7 를 눌러주거나  콘솔에서 가볍게 MSBuild.exe 를 쳐주시면 빌드가 진행됩니다.
당연히 예상하듯이 에러가 잔뜩 나올 것입니다. 여기까지가 첫째 코스 입니다.

에러코드를 살펴보시면 Complex 클래스가 없다는 이야기 부터 나올것입니다.  그러면 Complex 클래스를 작성해 줘야 겠지요? 이때 작성 순서는

'컴파일이 우선 가능하게 코드를 작성한다'

입니다.
complex.h 와 complex.cpp 를 추가합니다.

complex.h
class Complex
{
  friend bool operator==(const Complex& a, const Complex & b);
  double real , imaginary ;
 public:
  Complex (double r , double i = 0)
      : real(r) , imaginary(i)
  {
  }
};

comlex.cpp
#include "stdafx.h"
#include "complex.h"

bool operator== (const Complex &a , const Complex &b)
{
   return true; // 임시 방편임 컴파일만 가능하게..
}

그리고 complextest.h 에
#pragma once
#include <cppunit/TestCase.h>
#include "complex.h"
class ComplexNumberTest : public CppUnit::TestCase
{
 public:
 ComplexNumberTest( std::string name ) : CppUnit::TestCase (name ) {}
  void runTest ()
  {
    CPPUNIT_ASSERT ( Complex (10, 1) == Complex (10, 1));
    CPPUNIT_ASSERT ( !(Complex(1, 1) == Complex (2, 2)));
  }
};
붉은색 두줄을 추가해주면 Compile 은 성공합니다. 자 그러면 실행해볼까요? 실행하면 runTest 의 두번째 단언문에서 프로그램이 죽는 것을 알 수가 있습니다. 즉  operator == 가 제대로 안 만들어 졌다는 이야기 이지요 , 그렇다면 다음 과정은

'Test 가 성공하게 프로그램을 바꾸자'

입니다. 아직은 소스가 간단하니까 어디를 바꾸시면 되는지 금새 아시겠지요?

complex.cpp 입니다.

#include "stdafx.h"
#include "complex.h"

bool operator== (const Complex &a , const Complex &b)
{
  return a.real == b.real && a.imaginary == b.imaginary ;
}

이부분을 바꾸고 Build 하시고 실행하시면 프로그램은 문제 없이 돌아갑니다.
TDD 라고 해서 어려운 것이 아니고 제가 붉은 색으로 쓴 글을 반복하는 행위 입니다.

(컴파일도 안되는) Test Code 를 작성합니다. (실제 사용하는 사용자의 입장에서) - 컴파일이 되게 코드를 수정합니다. (모자라는 부분 이 있으면 추가를 해서 잽싸게 Compile 만 되게 만듭니다.) - Test 가 성공하게 프로그램을 수정합니다.

이 세가지 부분만 계속해서 반복하시면서 프로그램을 작성해 나가시는게 TDD 입니다.

많은 분들이 TDD 를 단위 테스팅 기법이라고 생각하시는 분이 많습니다. 그러나 실전에 도입해서 계속해서 사용하다 보면 TDD 는 '설계 나 분석' 기법에 가깝습니다.
컴파일 하면 TestRunner 쪽에서 에러가 발생합니다. 사실 TestRunner 없어도 cppunit 안에 Text 형식의 TestRunner 가 포함되어 있긴 하지만 (이걸 사실 제일 많이 씁니다)

그래도 안되는게 있으면 짜증이 나지요. 만지작 거리다 보니까 CPPUnit 쪽 위키에서 해결방안이 있더군요.

http://cppunit.sourceforge.net/cppunit-wiki/BuildingCppUnit1


('' 여기를 참조하시면 되고요. 실제로 수정하는 부분은

#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("7.0") lcid("0") raw_interfaces_only named_guids

여기서 7.0 인 부분을 8.0 으로 수정해 주시면 됩니다. .NET 2005 가 VC8.0 이기 때문입니다.

#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("8.0") lcid("0") raw_interfaces_only named_guids



즐겁게 TDD 를 응용하세요.

+ Recent posts