'테스트 주도 개발' 책에서 또 관심을 끌었던 부분입니다. 마치는 글을 마틴
파울러가 장식을 했군요.

그 부분도 올려봅니다.

 
테스트 주도 개발에 대해 설명하기 어려운 것 중 하나는 TDD를 하면
돌입하게 되는 정신상태다. C3 프로젝트에서 랄프 베티(Ralph Beattie)와
함께 했던 세션을 기억한다. 우리는 복잡한 지불 조건을 구현해야만
했다. 랄프는 그걸 여러 개의 테스트 케이스로 쪼갰고, 우리는 그것들이
작동하도록 하나씩 접근했다. 꾸준히 서두르지 않으면서
진행했다. 서두르지 않았기 때문에 느린 것처럼 보였지만, 얼마나 많은
일을 했는지 뒤돌아 보면 , 작업시의 느긋한 느낌에도 불구하고 진행
속도는 매우 빨랐다.
우리가 가진 화려한 도구들에도 불구하고, 프로그래밍은 여전히
어렵다. 동시에 여러 개의 공을 공중에 띄워놓고 저글링할 때처럼 ,
프로그래밍할 때도 잠시만 집중을 놓치면 모든 게 무너져 버릴 것 같은
느낌을 받은 적이 많다. 테스트 주도 개발은 이런 느낌을 감소시키는 데
도움이 되고, 그 결과로 신속한 느긋함을 얻게 된다.

 그렇게 생각하는 이유는, 테스트 주도 개발 스타일로 작업하면 한 번에
딱 하나의 공만 공중에 띄우는 느낌이 들고, 그렇기 때문에 그 공에
충분히 집중할 수 있고 그 일을 정말 훌륭히 해낼 수 있다는
것이다. 나는 새로운 기능을 추가하려고 할 때, 이 함수에는 정말 어떤
설계가 좋을지 고민하지 않고 , 할 수 있는 한 가장 쉽게 테스트를
통과시키려고만 노력한다. 리팩토링 모드로 바뀌면 새로운 기능을
추가하는 것에 신경 쓰지 않고, 올바른 설계를 얻는 데만 신경 쓴다. 이
양자를 통해 한 번에 딱 하나에만 집중하게 되고, 그 결과 그 한 가지에
대해 더 잘 집중할 수 있다.

 테스트 우선으로 기능을 추가하는 것과 리팩토링은 프로그래밍의 두 가지
단일사고적 특색이다. 최근 키보드를 두드리다가 또 다른 하나를 경험하게
됐다. 그것은 패턴 복사하기다. 데이터베이스에서 어떤 데이터를 가져오는
작은 루비 스크립트를 작성하고 있었다. 이 일을 하면서 데이터베이스
테이블을 감싸는(wrap) 클래스에 대해 작업을 시작했다. 그때 데이터베이스
패턴 책을 한 권 끝냈기 때문에 패턴을 하나 사용해야 한다는 생각이
들었다. 예제 코드는 자바였지만, 그걸 루비에 적용하는 건 어렵지
않았다. 프로그래밍하면서 문제에 대해서는 별로 생각하지 않고, 그 패턴을
현재 언어와 내가 다루던 특정 자료에 어떻게 멋지게 적용할까에 대해
생각했다.

 패턴 복사하기 자체는 훌륭한 프로그래밍이 아니다. 이 사실은 내가 패턴에
대해 이야기 할 때면 늘 강조한다. 패턴은 언제나 반숙 상태며, 자신의
프로젝트 오븐 속에서 적응시켜야 한다. 하지만 이렇게 하기 위한 좋은 방법
중 하나는 일단 무턱대고 패턴을 복사하고 나서, 리팩토링과 테스트 우선을
섞어 사용해서 그 적응과정을 수행하는 것이다. 패턴 복사를 할 때 이렇게
하면 해당 패턴에 대해서만 집중할 수 있게 된다(한번에 하나씩).

 XP 커뮤니티는 전체 그림에서 패턴이 어디에 위치해야 하는지 고심해
왔다. XP 주창자와 패턴 주창자들 사이에는 상당히 큰 일치점이 있기 때문에
(워드와 켄트는 두 분야 모두 리더다) XP 커뮤니티는 분명 패턴을
좋아한다고 볼 수 있다. 테스트 우선과 리팩토링이 그 자체로는 위험하지만
함께 하면 강력한 것처럼, 패턴 복사는 그 둘과 함께 가야 할 세 번째 단일
사고적 모드일지도 모르겠다.

 핵심 작업을 분간하고 한 번에 딱 하나만 집중하도록 하는 것이 어떤
활동을 체계화하는 데 주요한 역할을 한다. 조립 라인은 이런 예 중 정신을
멍하게 하는 예가 된다. 언제나 정해진 한 가지만 하기 때문이다. 아마
테스트 주도 개발이 제안하는 것은 프로그래밍의 행위를 여러 기본적 모드로
나누되, 그런 모드를 재빨리 전환해 가면서 단조로움을 피하는 것이지
않을까, 단일사고적 모드들과 전환의 조합을 통해 집중의 이득을 얻을 수
있고, 조립 라인의 단조로움 없이 뇌에 가해지는 스트레스를 낮출 수
있다.

 이 생각들이 다소 미숙하다는 것을 인정한다. 이 글을 쓰면서도 여전히
내가 하는 말을 스스로 믿는지 확신하지 못하고, 이 생각들을 몇 개월,
아니 꽤 오랫동안 고민할 것이라는 걸 안다. 하지만 어쨌거나, 테스트 우선
개발이 속하는 더 큰 그림에 대한 생각을 자극하기 때문에 독자가 내
아이디어를 좋아하지 않을까 하는 생각을 했다. 아직 우리가 분명히 볼 수
있는 그림은 아니지만 서서히 자신을 드러내고 있는 그림이라고 생각한다.


이 글은 실제로 TDD를 하면서 나타나는 일에 대한 집중도에 관해서 설명을
하고 있습니다. 저도 TDD를 쓰며 개발하면서 느끼는 것은 역시 일에 대한
집중도에 놀랐었는데, 마틴 파울러가 이 부분을 잘 지적을 하고 있는듯 합니다.

테스트 주도 개발 책을 읽으면서 그 책에서 제일 괜찮다고 생각하는
부분중에 한 부분입니다. TDD 개념을 가장 쉽게 접근할 수 있도록 만든
예제인데 무단으로 퍼서 소개할까 합니다. - 사실 본 책 안에 있는 내용은
좀 난해한 편이고 , 이 예제가 더 이해하기 쉽습니다. -

부록 B . 피보나치

이 책의 검토자 중 한 명의 질문에 대한 답으로 나는 피보나치 수열을
테스트 주도로 개발해 올렸다. 몇 명의 검토자들이 이 예를 보고 TDD가
어떻게 작동하는지 이해하는 데 큰 도움이 되었다고 했다. 하지만 이 책에
사용된 예제를 피보나치 예제로 바꾸기에는 피보나치 예제가 너무 짧고,
다양한 TDD 기술을 충분히 보여주지도 못한다. 이 책의 주 예제를 읽은
후에도 여전히 번쩍이는 깨달음을 얻지 못했다면 여기를 잠깐 들여다보고
머릿속 전등이 켜지는지 살펴보자.
 
첫 번째 테스트는 fib(0) = 0 이라는 걸 보여준다. 구현은 상수를
 반환한다.

 - 참고로 TDD는 실패하는 Test Code 부터 작성합니다.
 - 그리고 그것을 제대로 돌리기 위한 코드를 작성합니다.

public void testFibonacci () {
       assertEquals(0 , fib(0));
}

int fib(int n) {
    return 0;
}

(함수 하나밖에 안되기 때문에 나는 TestCase 클래스에 직접 해당 코드를
박아 넣구 있다)
 두 번째 테스트는 fib(1) = 1 이라는 걸 보여준다.

pulic void testFibonacci () {
      assertEquals (0 , fib(0));
      assertEquals (1, fib(1));
}

testFibonacciOfOneIsOne 이라는 테스트 메서드를 따로 작성하는 것에 큰
커뮤니케이션 가치가 있어 보이지 않아서 , 두 번째 단언을 같은 메서드
내에 집어 넣어 버렸다.
 이게 돌아가도록 하는 덴 몇 가지 방법이 있다. 나는 0을 특별한 경우로
 다루는 방법을 쓰겠다.

 int fib (int n) {
 if (n == 0) return 0;
 return 1;
}

테스트 케이스에 있는 중복이 점점 성가시게 느껴지기 시작하는데, 새
캐이스를 추가하면 더 악화되기만 할 것이다. 입력과 예상값으로 구성된
테이블을 통해 테스트가 돌아가게 하면 단언의 공통 구조를 추출할 수
있겠다.

public void testFibonacci () {
       int cases[][] = {{0,0} , {1,1}};
       for (int i= 0; i < cases.length ; i++)
           assertEquals(cases[i][1] , fib (cases[i][0]));
}

 이제 다음 케이스를 추가하려면 키보드를 여섯 번만 치면 되고, 줄을 새로
 추가할 필요는 없다.

 public void testFibonacci () {
  int case[][] = {{0,0} , {1,1} , {2,1}};
   for (int i=0 ; i < cases.length ; i++)
       assertEquals(cases[i][1] , fib(cases[i][0]));
}

당황스럽게도 테스트가 제대로 돌아간다. 우리가 고른 상수 1이 이
케이스에도 들어맞는 값이기 때문에 그런 일이 벌어졌다. 다음 테스트로
넘어가면

public void testFibonacci () {
  int case[][] = {{0,0} , {1,1} , {2,1}, {3,2}};
   for (int i=0 ; i < cases.length ; i++)
       assertEquals(cases[i][1] , fib(cases[i][0]));

}

야호, 이제 실패한다. 이전의 전략(더 작은 입력값을 특별한 경우로 다루는
것)을 똑같이 적용해서 다음과 같이 작성한다.

int fib(int n) {
    if (n == 0) return 0;
    if (n <= 2) return 1;
    return 2;
}

 이제 일반화할 준비가 되었다. 우리가 2라고 쓰긴 했지만 정말 2를
 뜻한것은 아니고 , 1+1 을 의미한다.

 int fib(int n) {
    if (n == 0) return 0;
    if (n <= 2) return 1;
    return 1+1;
}

첫 번째 1은 fin(n-1)로 볼 수 있다.

int fib(int n) {
    if (n == 0) return 0;
    if (n <= 2) return 1;
    return fib(n-1) + 1;
}

두 번째 1은 fib(n-2)로 볼 수 있다.

int fib(int n) {
    if (n == 0) return 0;
    if (n <= 2) return 1;
    return fib(n-1) + fib(n-2);
}

이제 좀 정리를 하면, 동일한 구조가 fib(2) 에서도 작동하기  때문에 결국
두 번째 조건을 강화할 수 있다.

int fib(int n) {
    if (n == 0) return 0;
    if (n == 1) return 1;
    return fib(n-1) + fib(n-2);
}

이렇게 해서 우리는 완전히 테스트로부터 유도된 피보나치를 완성하게
되었다.



제가 어디서 본 이야기인데 , TDD 를 단지 단위테스트 용 기법으로
생각하시는 분들이 많다고 합니다. 그러나 TDD는 '분석기법이고,
설계기법' 입니다. 그런것을 염두에 두시고 다시 한번 피보나치 구현을
보시면 TDD가 어떻게 설계에 쓰였는지 감을 잡으실 수 있을 것입니다.

회사에서 스마트폰 프로그램을 제작하는 일을 하게 되서 환경 세팅을 하고 있었습니다. 환경은 '블랙잭' 이 될 듯해서요.



ROUND 1


http://blog.nworkers.net/183

이분의 블로그를 참고 삼아서 개발 환경을 '블랙잭'에 맞게 세팅을 했습니다. 여기도 알바하시는 분이 잘 찾아오셔서 그대로 설치를 딱 하는 순간.. 언제나 그렇듯이 프로젝트가 생성이 안됩니다.  -0-

Error 는 1033 폴더 밑의 default.html 이 호출이 안된다는 것입니다.

정확한 위치는 아래 입니다.

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCWizards\SmartDeviceAppWiz\MFC\Application\html\1033\default.html

참 이것이 깔린 환경을 말씀드리자면

OS : Windows Server 2003 - 영문 버젼
개발툴 : Visual Studio .NET 2005 - 한글 버젼

이 두개가 묘한 시너지를 일으켜서 절대 스마트폰 프로젝트가 생성이 안되는 경지에 이르렀나 봅니다.

문제가 생기면 언제나 그렇듯이 신탁에 의존합니다. (신탁 = 구글링 )

답이 나옵니다. 일단 저에게 발생하는 문제가 언제나 그렇듯이 절대 한국에서는 잘 일어나지 않는 일입니다 -ㅅ-b

사이트 링크가 두개 나오더군요.

http://blogs.msdn.com/windowsmobile/archive/2007/01/08/ie7-and-smart-device-projects-in-vs-2005.aspx

이것이랑

http://blogs.msdn.com/fzandona/archive/2006/08/01/684927.aspx

이 두군데를 종합해 본 결과

Workaround 3: Unable to Create Native (C++) Projects
VC++ Project Wizards are pretty much HTML files + scripts - Visual Studio uses IE to render and present those "web pages" as a wizard. The problem is that, due to the new security model, IE7 does not trust some of those scripts; as a result you keep getting the "New Project" dialog and can't move forward on the wizard. The workaround here is to let IE know that the smart device VC++ wizard is a nice guy and ok to run.

You will need to open the registry entry: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Ext\PreApproved

And add a new entry named: {D245F352-3F45-4516-B1E6-04608DA126CC}


이런 문제라는 것에 결론을 내렸습니다. 대충 보자면 IE 가 방해를 한다고 하는군요.
그래서 위에 나온것처럼 레지스트리를 바꿔주고 , 다시 프로젝트를 생성해 봤습니다. 역시 안되는 군요. 당황해서 땀이 삐질 삐질 나오기 시작합니다. 옆에 있는 알바가 웃고 있는 듯한 환상도 느껴지기 시작합니다.
일단 더 창피해지기 전에 알바를 보냅니다.

ROUND 2

이제 밥도 먹구 힘이 좀 생깁니다. 그래서 다시 문제를 보기 시작했습니다. 위에 문제가 생긴다고 하는 곳에 가보면 1033 이라는 폴더가 없습니다. 대신 1042 만 있지요. 1042 를 안에 살펴보니 readme.txt 파일이 있더군요 열어보니 저의 자랑스런 모국어가 잔뜩 쓰여져 있습니다. 1033 이 혹시.. US 리소스를 모아놓는 곳이 아닐까? 싶습니다. 그래서 답이 의외로 간단할꺼라 여겨서 1042 폴더를 바로 그자리에 복사해서 1033으로 이름을 바꿔 놓습니다. 그리고 프로젝트를 생성해보니

오오!!! 프로젝트가 생성이 될려나 하는데 스크립트 에러가 팍팍 떠줍니다. 몬가가 이상한가 봅니다. 그래서 Visual Studio 의 메뉴를 보니

TOOLs - Option - Internet Option 이라는 메뉴를 보니 Windows 와 같음 이라고 세팅 된게 보입니다. 그래서 메뉴나 , 프로젝트 생성 이런것들이 전부 영어 인게 생각이 나서 그것을 눌러보니
English , Korean , Windows 와 같음  <- 이 세가지로 나뉘더군요 , 그래서 Windows 가 영문이라서 영문 환경이 된게 아닐까 해서 이것을 한국어로 바꾸어 주니

오옷 !!! 프로젝트가 생성이 되더군요. +ㅂ+ 뿐만 아니라 모든 메뉴들이 전부 한국어로 바꼈습니다. 별거 아닌 문제여서 자료가 없을것이라 생각해서 이리 글을 남깁니다...

사용자 삽입 이미지

여기는 한국 메뉴로 바뀐다음에 설정을 찾는 부분입니다. 도구(T) 라고 하는 부분을 클릭하시고 그 메뉴 맨 밑의 옵션(O).. 를 클릭해서 옵션 창을 띄웁니다.

사용자 삽입 이미지

여기서 국가별 설정 - 영문판에서는 Internet Option 으로 나왔음 - 을 한국어로 바꾸어 주시면 됩니다.

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

> 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 를 응용하세요.
사람이 어떻게 까지 게으를 수가 있는 것인지 !!!
아 물론 프로그래머의 영역은 조금 다르긴 합니다. 게으르면 게으를 수록 훌륭한 프로그래머 입니다. 사실은 전제 조건이 있지요 '자기 할 일을 한다는 전제하에 ' 말이죠.
자기 할일을 하면서 게으른 프로그래머가 최고지요 ^^;

사실 유닉스 쪽에서는 유명한 기술이라고 합니다. 견문이 짧은 제가 드디어 알게 된 것이긴 하지만 말이죠.

유닉스에서 프로그램을 만들기 위한 makefile 스크립트를 자동으로 생성하게 도와주는 자동화 툴입니다. (저는 이런것 무지 좋아합니다 +ㅂ+ )

Makefile.am 과 configure.ac 파일 두개만 생성시켜 주고 나서
콘솔에서 autoreconf -f -i 를 가볍게 입력해주면 자동화 스크립트가 모든 것을 알아서 해주는 군요!!!

아래는 생성해 줘야 할 두개의 파일 예제 입니다.

Makefile.am


# not a GNU package. You can remove this line, if
# have all needed files, that a GNU package needs
AUTOMAKE_OPTIONS = foreign 1.4
#SUBDIRS =
#################################

# sub Makefile.am ##################
INCLUDES = -I$(top_srcdir) $(all_includes)
#METASOURCES = AUTO
bin_PROGRAMS = tnc_db
tnc_db_SOURCES = main.cpp
#tnc_db_LDFLAGS = -l

('' 위의  파일은 SRC_ROOT 와 각 예하 SUB DIRECTORY 에 생성해 줘야 합니다.

아래 파일은 SRC_ROOT 에만 생성해 주면 됩니다.

configure.ac

AC_INIT(configure.ac)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(tnc_db, 1.0)

AC_LANG_CPLUSPLUS
AC_PROG_CXX
AM_PROG_LIBTOOL

AC_OUTPUT(Makefile)



제가 무식한 탓인지 저는 리눅스의 가장 기초적인 쉘을 잘 못 씁니다.
편리한 툴에만 익숙해져 있기 때문입니다. (그렇다고 쉘이 편하지 않다는게 아닙니다!!)

유닉스 친구계열들을 보면 환경변수에 값들을 등록시켜서 쓰는데 그 문법이

crazia>NAME=crazia
crazia>export NAME

식으로 등록합니다. 이걸 편하게 하기 위해서 shell 로 여러가지 환경 변수를 등록시키기 위해서 shell 로 작성을 합니다.

#!/bin/bash

export NAME=crazia
export HOBBY=game
export HOBBY2=sleep

이 shell 을 my.sh 라고 작성해서 실행 옵션을 줘서 실행시키면 아무 동작을 안합니다.

결국 이거저거 시도하다가 알아낸 방법은
source ./my.sh 라고 해주면 바로 적용이 됩니다.

이 글은 나중에라도 혹시 또 명령어를 까 먹을까봐 글을 남기는 것입니다 ^^;

MS에서 개발을 좋아하는 사람들에게 무료 개발툴을 배포한다는 소식을 늦게 접했습니다.

http://msdn2.microsoft.com/ko-kr/express/default.aspx

바로 여기가 그 사이트 입니다. 30일 트라이얼이지만 등록을 하면 무한대 가 되지요.
금전적인 이유가 아니라 저는 전혀 다른 이유로 설치했습니다. (사실 어둠의 경로를 이용하면 최상위 버젼인 Team Foundation 버젼을 설치가능합니다.)

제가 가지고 다니는 서브 노트북이 사양이 조금 후달리다 보니, 자연스럽게 통합 스튜디오인 .NET 버젼을 설치한다 해도 심하게 버벅입니다. 그래서 가벼운게 없나 찾아보던중 Express 가 있더군요. 간단한 공짜 IDE도 제공하고 아주 맘에 듭니다. C#은 C#만, C++은 C++ 만의 각자 IDE를 제공합니다. - .NET 버젼은 한개에서 모든 것이 전부 사용가능하 구조이지요.

설치도 어려운게 아니고 잘 돌아가는 것을 확인하고 덩치도 별로 안크고, 사양도 많이 안탑니다. 괜찮지 않습니까? 게다가 '공짜' 입니다 ㅋㅋ

+ Recent posts