E D R , A S I H C RSS

Cpp Unit

1. 설치

Visual C++ 6.0 기준으로 설명한다. 다른 언어들에 비해 환경설정을 위해 해야 할 부분이 많으므로 인내심을 가지고 따라해야 한다.

1.1. 준비 1 - 다운 받고 한번 이상 꼭 해주어야 할 사항

1.1.1. Library 화일 생성하기

처음 압축화일을 받고 풀면 lib 폴더에 Library 관련 화일들이 없다. 이것을 만드는 방법

  • Library 화일 생성 : ~cpp ...cppunitexamplesexamples.dsw 을 연뒤 ~cpp WorkSpace ~cpp FileView 에서 ~cpp CppUnitTestApp files 에 Set as Active Project로 맞춰준다.(기본값으로 되어 있다.) 그리고 컴파일 해주면 lib 폴더에 library 화일들이 생성될 것이다.
컴파일 후 실행해 보면 다음과 같은 (혹은 비슷한) 결과를 볼수 있다.
이로서 가장 기본이 되는 셋팅은 완료된다.

1.2. 준비 2 - CppUnit을 사용할 프로젝트 열 때 해주어야 할 기본 세팅

1.2.1. include, library directory 맞춰주기 (둘중 하나를 선택한다.)

Library : ~cpp ...cppunit-x.x.xlib

Include : ~cpp ...\cppunit-x.x.xinclude
  1. 전체 세팅 변경시
    1. Tools -> Options -> Directories -> Include files 에서 해당 cppunit
    2. Tools -> Options -> Directories -> Library files 에서 역시 lib
  2. 해당 프로젝트에만 적용시
    1. Project -> Settings -> C/C++ -> Preprocessor -> Additional include directories
    2. Project -> Settings -> Link -> Input -> Additional Library directories

  1. RTTI 를 체크해준다.
  2. Project Setting - Link - General - object/library 에 cppunitd.lib, testrunnerd.lib 를 추가해준다.
  3. 해당 프로젝트가 있는 곳의 debug 등의 디렉토리에 해당 lib 디렉토리에 있는 testrunnerd.dll 을 복사해준다. 이는 Project Setting - Post-Build-step 의 Post-build-command 에 다음을 추가해주면 컴파일 할때마다 dll 화일을 자동으로 복사해준다.

~cpp 
copy c:cppunitlibtestrunnerd.dll .
  • Project Setting - Code Generation - Use Run-Time library 를 다음으로 맞춰준다.
    • Release Mode : Mulithreaded DLL
    • Debug Mode : Debug Multihreaded DLL
  • app 클래스에 다음과 같은 runner 실행을 위한 코드를 추가한다. 다음 코드를 추가함으로써 프로그램 실행시에 GUI Test Runner 가 실행된다.

~cpp 
#include <msvc6/testrunner/testrunner.h>
#include <cppunit/extensions/testfactoryregistry.h>
.
.
.
BOOL CMyApp::InitInstance () {
.
.
    // Dialog Based 의 경우는 dlg.DoModal ()을 실행하기 전에 적어준다.
    TestRunner  runner;
    runner.addTest ( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );
    runner.run ();
}

2. UnitTest TestCase의 작성

Test Case 가 될 Class는 ~cpp CppUnit::TestCase 를 상속받는다.

2.1. ExampleTestCase.h

~cpp 
#ifndef CPP_UNIT_EXAMPLETESTCASE_H 
#define CPP_UNIT_EXAMPLETESTCASE_H 
 
#include <cppunit/TestCase.h> 
#include <cppunit/extensions/HelperMacros.h> 
 
class ExampleTestCase : public CppUnit::TestCase 
{ 
  CPPUNIT_TEST_SUITE( ExampleTestCase );      // TestSuite
  CPPUNIT_TEST( testExample );                // TestCase 의 등록.
  CPPUNIT_TEST_SUITE_END();                   // TestSuite 의 끝. 이로서 해당 Test Case 에 자동으로 suite 메소드가 만들어진다.
protected: 
        void                    testExample (); 
public: 
        void                    setUp (); 
        void                    tearDown (); 
}; 
#endif 

2.2. ExampleTestCase.cpp

~cpp   
#include "stdafx.h"                      // MFC 인 경우.
#include "hostapp.h"                     // MFC 인 경우 해당 App Class
#include "ExampleTestCase.h" 
 
CPPUNIT_TEST_SUITE_REGISTRATION( ExampleTestCase );      // TestSuite 를 등록하기. TestRunner::addTest 가 필요없다.
 
 
void ExampleTestCase::testExample ()     // 테스트 하려는 함수.
{ 
        CPPUNIT_ASSERT (1 == 2); 
} 
 
void ExampleTestCase::setUp ()          // fixture 관련 셋팅 코드. 
{ 

} 

void ExampleTestCase::tearDown ()       // fixture 관련 셋팅 코드.
{ 

} 
 
~cpp 
#include <iostream> 
using namespace std;

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

#ifndef _SIMPLE_H_
#define _SIMPLE_H_

#include <cppunit/TestCase.h>
#include <cppunit/extensions/HelperMacros.h>

class SimpleTest : public CppUnit::TestFixture { 
public: 
	CPPUNIT_TEST_SUITE( SimpleTest );
	CPPUNIT_TEST ( testOne );
	CPPUNIT_TEST ( testTwo );
	CPPUNIT_TEST_SUITE_END();

	void testOne () {
		CPPUNIT_ASSERT( 1 == 2 );
		CPPUNIT_ASSERT( 3 == 4 );
	}

	void testTwo () {
		CPPUNIT_ASSERT( 1 == 1 );
		CPPUNIT_ASSERT( 3 == 3 );
	}

};

#endif

int main( int argc, char* argv[] )
{
	CppUnit::TextUi::TestRunner runner;
	CppUnit::TextTestResult result;
	
	runner.addTest (SimpleTest::suite());
	
	runner.run("", false);

	return 0;
}

2.2.1. GUI Test Runner 의 이용

GUI Programming 을 하기 위해 winmain 이 시작인 코드의 경우(MFC GUI Programming 포함) 콘솔창이 뜨지 않는다. 이 경우 GUI Runner 를 실행해줘야 한다.
~cpp 
#include <cppunit/ui/text/TestRunner.h>

~cpp 
#include <cppunit/ui/mfc/TestRunner.h> 
로 수정한뒤, testrunnerd.dll 를 해당 프로젝트화일에 복사해주면 된다.

Runner 실행코드는 다음과 같이 MFC UI 의 Test Runner 를 이용한다.
~cpp 
	CppUnit::MfcUi::TestRunner runner;
	CppUnit::TextTestResult result; 
	
	runner.addTest (SimpleTest::suite()); 
	
	// runner.run("", false); 
	runner.run();

2.2.2. Win32 API or Console 프로그래밍시

Win API Programming 시에 Text Runner 를 이용하여 이용 가능. 다음과 같은 식으로 쓸 수도 있다.
~cpp 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE, LPSTR, INT) {

	CppUnit::TextUi::TestRunner runner;

	CppUnit::OStringStream stream;
	CppUnit::TextOutputter* outputter = new CppUnit::TextOutputter(&runner.result(), stream);

	runner.setOutputter(outputter);	

	runner.addTest(SimpleTest::suite());

	runner.run();

	MessageBox(NULL, stream.str().c_str(), "Test", MB_OK);	

	return 0;
}


~cpp 
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>

class SimpleTestCase : public CppUnit::TestCase {
public:
	CPPUNIT_TEST_SUITE ( SimpleTestCase );
	CPPUNIT_TEST(testOne);
	CPPUNIT_TEST(testTwo);
	CPPUNIT_TEST_SUITE_END();
public:
	void testOne() {
		CPPUNIT_ASSERT_EQUAL(10,10);
	}
	void testTwo() {
		CPPUNIT_ASSERT_EQUAL(20,20);
	}
};
CPPUNIT_TEST_SUITE_REGISTRATION (SimpleTestCase);

int main() {
	CppUnit::TextUi::TestRunner runner;
	CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
	runner.addTest(registry.makeTest());
	runner.run();

	return 0;
}

2.2.3. assertEqual 의 이용

코드를 보면 알겠지만, ASSERT 문들에 대해서 전부 매크로를 이용한다. 만일 이를 다른 언어들의 UnitTest Framework 처럼 assertEqual 이나 assert 문으로 쓰고 싶다면, 다음의 문장을 cppunit library 를 include 하기전에 추가해준다.
~cpp 
#define CPPUNIT_ENABLE_NAKED_ASSERT 1

기타 자세한 내용들은 (flag 들) cppunit/portability.h 를 참조하면 된다.

2.2.4. 주의점

  • 초기 준비할때 삽질하는 경우가 많다. -_-; CppUnit 의 경우는 헤더화일들의 include 순서들이 중요하다. 그리고 MFC 의 경우는 stdafx.h 를 각각의 화일들마다 include 해줘야 한다. (API에서 CppUnit 는 어떨지 궁금해진다.)
  • 중간중간에 Rebuild 해줄 필요가 있다. (제대로 했다고 생각했는데 Test Case가 Failure 가 나는 경우에는 한번 의심할 필요가 있다.)
----
MSVC에서 에러가 나는 경우 대부분은 CppUnit FAQ를 참고하면 해결할 수 있다. http://cppunit.sourceforge.net/FAQ


~cpp 
2) Questions related to Microsoft Visual VC++

2.1) Why does my application crash when I use CppUnit?
   
   You probably forgot to enable RTTI in your project/configuration. RTTI are disabled by default. 
   Enable RTTI in Projects/Settings.../C++/C++ Language. Make sure to do so for all configurations.

2.2) Why does the compiler report an error when linking with CppUnit library?

   You most likely are not using the same C-RunTime library as CppUnit.
   In Release configuration, CppUnit use "Mulithreaded DLL".
   In Debug configurations, CppUnit use "Debug Multihreaded DLL".
   Check that Projects/Settings.../C++/Code Generation is indeed using the correct library.

----
1.9.10 버전을 기준으로 VC++ 7.0 (VS.NET) 환경 세팅을 보인다.

2.2.5. 준비 - 1 lib, dll 만들기

1.9.10 은 sf.net 에 릴리즈 되어 있지 않다.
http://cppunit.sourceforge.net/snapshot/ 에서 받아올수 있다.
CppUnitCompile0.GIF
VC++ 6.0 파일을 받으면
CppUnitCompile2.GIF
이렇게 변환되어 컴파일 가능하다. 두개의 프로젝트가 에러남, 하지만 dll, lib 생성에는 지장없음
CppUnitCompile3.GIF
다음과 같은 파일들을 Test Case를 작성할 프로그램에 필요하다.

2.2.6. 준비 - 2 TestCase 만들기를 위한 세팅

CppUnitSettigDirectory0.GIF
다음과 같은 디렉토리 상태라고 가정한다.
CppUnitSettigInclude0.GIF
Include 시켜야할 디렉토리 추가(cppuint src 들어 있음)
CppUnitSettigLib0.GIF
라이브러리 디렉토리 세팅
CppUnitSettigLib1.GIF
라이브러리 추가
CppUnitSettigRuntime0.GIF
런타임 환경 세팅
----
싱가폴 국립대학의 소프트웨어 공학 프로젝트 수업에서 CppUnit을 사용하고 있는데, http://www.comp.nus.edu.sg/~cs3214s/tools/cppunitVC.html 에 가면 MSVC에서 CppUnit을 사용하는 방법을 쉽게 설명한 안내서를 볼 수 있다.
학교 수업에서 CppUnitCVS를 실제로 쓴다는게 신기하다는; --1002
학교 수업에서 실질적이고 현장에서 직접 쓰이는 도구들을 사용하도록 유도하는 것이 정말 부럽고, 국내 프로젝트/실습 수업에서 그냥 교재의 챕터 하나씩 발표시키고 이를 지켜보고, 평가하고, 끝에 지엽적인 질문으로 발표자 골탕 먹이는 일 외에도, 교수(혹은 조교)가 해 줄 수 있는 것이 이렇게 많다는 것이 신기하다는; --JuNe
  • vc7 용 cppunit 은 없나요.? 환경이 너무 많이 바뀌어서 저걸 적용하려니까 힘드네요..-_- (인스톨 도큐먼트 보니까 최소 6.0이라고 나와있기는 하던데..) 임인택
    vc7 도 똑같이 하면 됨. 단, 프로젝트의 라이브러리 설정이 vc7 의 다른 메뉴에 있어서 그렇지. --1002
  • 전 "Project Setting - Link - General - object/library 에 cppunitd.lib, testrunnerd.lib 를 추가해준다."라고 해서 추가 해줬더니
linking...
LINK : fatal error LNK1104: cannot open file "cppunitd.lib,"
Error executing link.ex

라고 link에러가 나는데 왜 그렇죠? 흐 무척 삽질하고 있습니다.-- FredFrith

library path 문제일 것 같은데요. 아니면, CppUnit 이 컴파일 되어있는지 확인해야 할것 같습니다. (lib 디렉토리에 cppunitd.lib 화일이 있는지 확인) --1002

  • VC6에서 작업하고 있는데요. CFileDialog를 통해 파일 path를 받으려고 하는데, TestRunnerCFileDialog 명령을 수행하는 것보다 먼저 동작해 파일 경로를 받을 수 없습니다.. TestRunner가 실행되는 시점을 조절할 수 있나요? --FredFrith
어떠한 부분을 테스트하고 싶으신건지 궁금합니다. (테스트 대상이 되는 코드부분과 테스트 코드를 보여주시면 좀 더 도움이 될듯합니다.) --1002

* 공간이 좁아 전부 올리기가 힘든데, file upload 할 수는 없나요? -- FredFrith

* 웹서핑을 통해 이곳에 왔습니다. 위에서 ExampleTestCase 클래스와 SimpleTest와의 관계는 어떻게 됩니까?
main에서는 ExampleTestCase를 사용하지 않는데요...

Win32 API환경에서 MFC TestRunner를 사용하는 방법을 찾았으면 좋겠군요. 여러가지로 시도해보았는데 MFC에 대한 지식이 너무 부족해서 계속 실패하네요. --응준

GUI Runner 말씀이신가요? 실험 좀 해보고 리플하겠습니다. --1002

이 부분에 나오는 Code Generation부분이 어디에 있는지 찾지를 못 하겠네요. 메뉴가 숨어있기라도 한 건지...@-@;; --leoanrdong
~cpp 
Project Setting - Code Generation - Use Run-Time library 를 다음으로 맞춰준다. 

Release Mode : Mulithreaded DLL 

Debug Mode : Debug Multihreaded DLL 
- C/C++ 탭에 보면 category가 있는데 거기에 code generation 이 있습니다. - 임인택
고마워요. 해결하고 이제 돌릴 수 있네요 :) -Leonardong

또 이 부분은 제대로 작동하지 않는 듯 하네요. 복사가 안 되어도 작동은 하니까 아직까지 문제는 없습니다만;;-Leonardong
~cpp 
copy c:cppunitlibtestrunnerd.dll .

아래 두 부분을 새 프로젝트 생성시 자동으로 추가되게 하는 좋은 방법 없나요. 매번 하려니 불편하네요; -- 황재선
{{|
Project Setting - Link - General - object/library 에 cppunitd.lib, testrunnerd.lib 를 추가해준다.
~cpp 
copy c:cppunitlibtestrunnerd.dll .
|}}
----
kldp.net 에 c 를 위한 UnitTest Framework 프로젝트가 있었네요. http://kldp.net/projects/act/
----
UnitTest
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-05-27 07:09:19
Processing time 0.0425 sec