ECB (Emacs Code Browser ) 세팅하기

 - crazia 가 세팅하는 방식에 대한 기억 유지 차원 정리

1. ECB package 받아서 .emacs.d 디렉토리에 압축을 풀어서 정리합니다.
 - 설치한다고 바로 ECB 가 구동은  안될것입니다. 기본적으로 필요한
  몇가지 라이브러리가 있습니다.

 1.1 여러가지 라이브러리를 전부 찾아서 설치할 수도 있지만 간편하게
  CEDET 한방으로 해결하는 방법을 선호합니다. 단 CEDET 설치하게 되면
  emacs 구동시 현저하게 느려진 기분을 만끽하실 것입니다.

  1.1.1 CEDET 를 받아서 .emacs.d 디렉토리에 압축을 풀어서 정리합니다.
   - CEDET 은 ~/.emacs.d/cedet-1.0pre4 에 설치될 것입니다.
   - .emacs 파일에 (load-file  "~/.emacs.d/cedet-1.0pre4/common/cedet.el")
     를 추가해 줍니다. 이렇게 하면 CEDET 설정은 끝입니다.

2. (add-to-list 'load-path "~/.emacs.d/ecb-2.32") 라고 .emacs 파일에
 추가해주는데, 이는 ecb 패키지에 대한 패스 추가라고 볼 수 있습니다.
 역시 .emacs 파일에 (require 'ecb) 라고 추가해 주면 ecb 설정 완료 입니다.



- sybase iq 는 메타 디비의 형태이다.
- sybase iq 에 접근을 위해서는 odbc 나 oledb 방식을 써야 합니다.
- odbc 방식은 사실 귀찮게 세팅해줘야 할 것이 많습니다. 따라서
  일반적으로 프로그래밍을 할때는 oledb 방식을 많이 씁니다.

- sybase iq 는 Adaptive Server Anyware (줄여서 ASA) 로 제어를 하게
  되는데 다음에 나오는 예제는 ASA 를 OleDB 를 이용해서 접근하는 방법을
  C# 으로 표현했습니다.

- oledb 방식을 쓸려면 iq 용 클라이언트를 설치해야 합니다. (그 안에
  oledb provider 가 포함)

 예제) 

using System.Data.OleDb; // 네임스페이스 추가


  string cnStr =
  "Provider=ASAProv.90;Eng=rskrt;Uid=rskrt;Pwd=password;Links=tcpip(Host=100.254.17.51)";
  // eng 는 디비 이름입니다.
  OleDbConnection Conn = new OleDbConnection(cnStr);

  try
  {
      Conn.Open();
  }
  catch (OleDbException ex)
  {
      MessageBox.Show(ex.Message);
      return;
   }

   MessageBox.Show("connection Success");

  http://www.connectionstrings.com/?carrier=sybase (참고 사이트)

emacs 를 사용하면서 사용 안 하다가 최근에 사용하게 된 모드가 '달력
모드' 입니다. Outlook 이라는 일정관리의 강자가 있지만 , 개발모드로
진입하게 되면 메일 관련 확인빈도가 떨어질뿐만 아니라 컴퓨터 리소스를
잡아먹는 괴물인 Outlook 을 항상 켜두지 않기 때문에 종종 간단한 일정
관리를 위해서 '달력 모드'를 씁니다.

M-x calendar 를 입력하면 구동되는데 , 간단한 사용은 이동이야 일반적인
Emacs 커서 이동과 같고 , 일정 입력은 %HOME% 디렉토리에 diary 파일을
만들어 두면 '달력모드'에 일정을 추가할 수가 있게 됩니다. (%HOME% 은
특별히 지정하지 않았을 시에는 Window 에서는 "C:\" 입니다.)

달력에서 이벤트가 있는 위치로 이동하셔서 i-d (i 키를 누르고 d 키를
바로 누름) 키를 누르면 그날에 필요한 일정을 기입할 수가 있습니다. 다
쓰고 다이어리 파일을 저장시켜주시면 (C-xC-s) 일정이 기록됩니다.

특정한날에 기입된 일정이 보고 싶으시면 날짜로 커서를 옮기고 'd' 를
누르시면 그날의 일정이 보입니다. 전체적인 다이어리 목록을 보고
싶으시면 's' 를 누르시면 전체적인 일정 목록이 나타납니다.

기간동안 일어나는 일정을 적어두고 싶으면 (예를 들면 휴가) C-S(space)
를 시작점을 잡고 날짜를 이동시킨후에 i-b 를 클릭하시면 구간에 관한
일정을 적어둘 수가 있습니다.

또한 Emacs 처음 구동시 (전 출근하자 마자 구동시킵니다) 일정을 보고
싶으면 .emacs 파일에 간단하게 (diary) 항목만 추가 시켜주면 일정이
보입니다.

역시 emacs !! 그 프로그램 근처를 떠날 수 없게 만드는 마력이 있습니다. ^^

최근에 개발을 진행하게 되었습니다. 개발환경에 대한 설명은 간단하게
말씀드리자면 기존의 심리행동을 측정하는 프로그램이 상당히
낙후됐습니다. DOS 시절 프로그램을 쓰고 있는 현실이지요. 윈도
어플리케이션이 있지만 이 또한 Windows 3.1 시절의 프로그램입니다. 물론
이들이 요즘 나오는 OS 에 설치가 된다고는 하지만 아무래도 오래전
프로그램 이다보니 효용성이 많이 떨어지는 환경입니다.

이 프로그램이 어떻게 쓰이는 지에 대해서 알아보기로 합니다.

조그만 방에서 어린이와 어머니가 한방에 있습니다. 그리고 관찰자들은 방
밖에서 어린이를 관찰하며 정해진 시간동안 어린이가 보여주는 행동을
관찰하여 그 행동사항을 기입하는 프로그램 입니다.

커다란 방과 중앙통제실에서 프로그램을 띄우고 방안이 보이는 유리창은
물론 관찰대상의 얼굴이 클로즈업 된 카메라가 설치되서 그 모든 행동을
녹화하면서 진행되는 영화같은 장면이 아니기 때문에 , 실제로 실험은
상당히 조악합니다. (영화에 비하면 말이죠)

그냥 프로그램이 설치된 노트북을 들고 조그만 유리창으로 쳐다보면서
관찰의 내용을 기입하는 방식인데, 노트북이 참 편리한 컴퓨터이긴 하지만
아무래도 이 실험에 대한 휴대성은 떨어지지요.

그래서 PDA 를 가지고 이런 작업을 하면 유용합니다. 노트북 대신 PDA를
들고 관찰을 하는 것이지요. 크기가 작으니 한손에 들고 쳐다보면서 상황이
발생할때마다 클릭 클릭 하는 것입니다.

프로젝트의 주요 목적은 관찰대상을 관찰하며 얻어지는 데이터를 편하게
저장할 수 있는 PDA 용 데이터 수집기를 만드는 것이 목표입니다.

개발 환경

OS : Windows XP , Windows Vista
TOOL : Visual Studio 2008 Professional Beta
     - 돈이 안들길래 받아서 설치했습니다.
Target Machine : SPH-M8100

구체적으로 개발은 Mobile 환경에서 개발하게 됩니다. 그를 위해서 기존의
개발툴만 깔려 있는 상태에서는 개발이 이루어 질 수가 없습니다. 개발용
SDK 와 테스트를 위해서 필요한 기기 Image 가 필요합니다.

1. Windows Mobile 5.0 Pocket PC SDK 를 설치한다.
   - 삼성 SPH-M8100 은 포켓피씨 OS 고 관련 SDK 를 설치해야
   포켓피씨에서 돌아가는 프로그램을 만들 수가 있다.
2. Windows Mobile 6 Professional Images (KOR) 이 설치한다.
   - 테스트를 위해서 이미지 종류중에서 KOR 버젼을 골라서 설치를 해야
   한다.

위의 두가지가 제대로 설치됐으면 설치 됐는지 확인하는 과정이
필요합니다. 간단한 Hello World 어플리케이션 한번 만들어 보기로 하지요

사용자 삽입 이미지

 ( 우.. 이 그림 캡쳐해서 올리다 보니 그림 크기 같은거 조절이 힘드네요. 회사에서 만든 웹 에디터로 글 쓰고 싶다는 생각이 팍팍 드네요 ㅎㅎ )

SmartDevice 에서 MFC Smart Device Application 선택해서 프로젝트 이름 기입해주면 됩니다.
 - 글씨체가 이상한건 취향입니다 ^^;

그 다음 진행은 Wizard 화면이 나옵니다. 적당히 "Next" 버튼을 눌러서 다음 화면에서 개발 플랫폼을 정해줍니다.

사용자 삽입 이미지

SPH-M8100 같은 경우는 Pocket PC SDK 5.0 으로 충분하고요, 블랙잭 의 경우는 5.0 SmartPhone SDK 로 컴파일 해야 합니다. 사실 둘의 차이는 타겟 플랫폼의 차이일뿐 개발요소는 거의 동일합니다.

 
사용자 삽입 이미지

간단한 application 이니 Dialog Based 로 만들어 보기로 하지요 , 실제로 PDA 자체에서 돌아가는 프로그램을 만들때는 Single Document 를 선호하긴 합니다. 몇가지 이유에서 말이죠
그리고 SPH-M8100 은 한글 OS니 리소스를 한국어로 설정하는 것 잊지 마시고요.

그 다음에 "Next"를 연타해서 프로젝트를 생성합니다.

사용자 삽입 이미지
프로젝트에서 "Resource" 탭을 여시고 "HelloWorldppc.rc" 쪽 리소스를 엽니다. 이름에서 눈치 채셨겠지만, ppc 는 Pocket PC 용 입니다. sp 라고 붙은 것은 스마트폰 용이지요.

다음과 같이 가운데 부분의 Static Text Control 에 적혀 있는 내용을 "Hello World" 로 바꾸어 줍니다.

사용자 삽입 이미지

이제는 컴파일 하고 가상 머신 이미지에 배포해보는 일만 남았습니다.

사용자 삽입 이미지

위에 타겟 플랫폼을 Pocket PC 용인지 확인하시고 빌드를 시작합니다.

사용자 삽입 이미지

빌드 성공!! 이제 준비된 가상 머신에 배포를 해보도록 하지요.

사용자 삽입 이미지
위 그림을 보시면 아시겠지만, 기본으로 제공된 가상머신 이미지에는 한국어 버젼이 없습니다.
그래서 가상머신을 바꿀 필요가 있는데 솔루션의 속성창을 엽니다. (여는 방법은 Solution tab 에서 오른쪽 마우스를 클릭하시고 맨 아래에 있는 "property" 메뉴를 클릭합니다.)

사용자 삽입 이미지
"Deployment" 부분에서 Deployment Device 부분을 KOR Windows Mobile 6 Professional Emulator 로 바꾸어 줍니다. 그리고 변견된 부분을 적용하시고 설정창을 닫으신 다음에 Debug 메뉴에서 "Start Debugging" 을 선택해주시면 됩니다. ( Visual Studio 6.0 스타일로 해둔 저는 F5 를 누르면 됩니다 )

사용자 삽입 이미지


 눈이 좀 침침해서 큰 화면이 필요하다고 생각되시면 KOR Windows Mobile 6 Professional VGA Emulator 로 배포하시면 됩니다. 한 4배정도 되는 화면이 나타납니다 ^^

한글 OS 니까 , 한글로 출력도 해보았습니다. 아까 Hello World 라고 친 Static Text 에서 한글로 바꿔주기만 해도 됩니다.

사용자 삽입 이미지

여기까지 Pocket PC용 프로그램을 만들기 위한 기본환경 세팅을 알아보았습니다. 이정도만 해도 기존의 MFC 프로그램에 익숙하신 분들은 생각나는 모든 형태의 프로그램을 만드실 수가 있을 것입니다.

다음에는 실제로 실용 팁 정도로 꾸며볼 예정입니다. (너무 밝히면 계약 위반이라 ...) 몇가지 기능이 추가된 페이지 한개만 만들어 보는 것으로 꾸밀 예정입니다.

기본적으로 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 이 아니라는 점도 마음에 걸려 , 결국 이런 방법을 쓰게 되더군요. 이것때문에 한 일주일간 남는 시간 틈틈이 작업을 한 것 같습니다. ^^; 편하게 할 수 있는 방법들을 찾아서 하세요.
기존의 CruiseControl.NET 에서 TestProject 를 실행해야 하는 경우가 있습니다. 그때는 <task> 블록에서 <exec> 블록을 이용해서 TestProject 의 결과물을 호출합니다.

ccnet.config 에서 <task> 블록에서 <exec> 블록을 추가해줍니다.

     <exec>
  <executable>D:\User\Crazia\Work\win2007d\build\Test2007d.exe</executable>
        <baseDirectory>D:\User\Crazia\Work\win2007d\build</baseDirectory>
        <buildTimeoutSeconds>10</buildTimeoutSeconds>
    </exec>

<executable> 에 실행 파일을 적어주고 <task> 블록안에 넣어주시면 됩니다. 저는 <devenv> 블록 다음에 바로 넣어줬습니다.




지금까지 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>

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

TestRunner 에서 봤듯이 Fixture 에는 Static 함수는 suite() 가
필요합니다. 하지만 이것을 매번 작성하다보면 , 내용이 귀찮고,
반복적으로 해야 하고 그러다 보면 실수를 유발하게 됩니다. 그래서
이부분을 편리한 매크로로 만들어서 쓰게 할 수 있습니다.

기존의 파일에서

#include <cppunit/extensions/HelperMacros.h>

를 추가하면 macro를 쓸 수 있게 해줍니다.

CPPUNIT_TEST_SUITE ( ComplexNumberTest) ;

('' 이것을 선언해주면 suite 를 쓰겠다고 선언하는 것입니다.

suite 에 추가해줄 함수들을 추가하고요

CPPUNIT_TEST (testEquality ) ;
CPPUNIT_TEST (testAddition ) ;


그리고 suite 선언이 끝났다고 선언해주는 것입니다.

CPPUNIT_TEST_SUITE_END () ;


여기까지 차례로 쓰면 , 아래 나와 있는 메서드 전체를 선언 과 구현해준
것입니다.

static CppUnit::TestSuite * suite () ;

나머지 부분들은 기존과 동일하게 처리하시면 됩니다.

complextest.h 를 보기로 하지요

class ComplexNumberTest : public CppUnit::TestFixture  {
 private:
  Complex *m_10_1, *m_1_1, *m_11_2;
 public:

  CPPUNIT_TEST_SUITE( ComplexNumberTest );
  CPPUNIT_TEST( testEquality);
  CPPUNIT_TEST( testAddition);
  CPPUNIT_TEST_SUITE_END();


 public:
  void testDivideByZeroThrows ()
  {

  }
  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 );
  }

};



EXCEPTION 부분은 생략하기로 합니다.


TestFactoryRegistry

TestFactoryRegistry 는 두가지 이유로 씁니다.
 fixture suite 를 테스트 러너에 추가하는 것을 가끔 잊어먹을때가
 있습니다. 다른 파일에 보통 fixuture 가 있기 때문에 종종 그렇게
 잊어먹곤 합니다.

 test case 의 모든 헤더를 한곳에 집중해서 선언하면 컴파일 할때 병목
 현상이 생기기 때문입니다.


다음의 예를 봅시다.

ComplexNumberTest 를 등록 시키기 위해서는 .cpp 파일에 다음과 같이
추가합니다.

CPPUNIT_TEST_SUITE_REGISTRATION ( ComplexNumberTest) ;

이 이면에는 AutoRegisterSuite 의 static 변수가 선언되어 , 생성시에 그
변수가 TestSuiteFactory 를 TestFactoryRegistry 에 등록시킵니다. 그리고
TestSuiteFacctory 가 ComplexNumberTest::suite() 에 의해 반환되는
TestSuite를 반환합니다.

주절 주절 말을 늘어놓아지만 결국 할 이야기는 TestSuite 를 짜고 등록을
시키면 나중에 한꺼번에 몰아서 호출이 가능하다는 이야기 입니다.

실제로 이 테스트를 실행시키려고 하면 우리는 더이상 주저리 주저리
헤더를 등록 시킬 필요 없이

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

Factory 와 TestRunner 만 인클루드 시키면 됩니다.


 
CppUnit::TestFactoryRegistry & registry =
 CppUnit::TestFactoryRegistry::getRegistry();


이렇게 하면 CPPUNIT_TEST_SUITE_REGISTRATION () 를 통해서 등록한 모든
test suite를 가져올수 있습니다.

 
runner.addTest (registry.makeTest () );
 runner.run () ;

 return 0 ;

이렇게 실행합니다. (기존의 코드를 지우고 새로 위의 코드들을 써 넣으십시요)

main 함수가 간단해 지고 , 간결해 지는 장점이 있습니다.


Post build Check 부분은 나중에 따로 다른 예로 설명 드리고 CookBook 은
여기서 마치는 걸로 하겠습니다.

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 정보입니다. ( 애매해서 의역이 심하네요 ㅎㅎ)



 

+ Recent posts