Confidential
S/W Unit Test & TDDVer 1.0
GSD / Base Solution Team
jiman.Ham
2008. 3. 14
시작하기에 앞서
22008-03-11
마음을 열고(Open-Mind), 일단 한번 들어봅시다.혹시나 우리의 열정(Heart)이 다시 뛰게 할 지도 모르니까요.
What the hell is your problem?
32008-03-11
테스트 おげんきですか?
난 테스트를 잘하고 있습니다. (테스트げんきです.)
- 어떤 단계의 테스트를 현재 짂행하십니까?
• Smoking Test
• Boundary Test
• Random Test
테스트는 QA가 하는 읷 아닌가요?
• Black Box Test vs White Box Test
• 최고의 QA팀이 있어도 버그는 막을 수 없다.
• 마감 직젂에 발견되는 버그가 가장 큰 문제를 읷으킨다.
부실한 테스트의 피해자는 프로그래머
• 욕먹고 야귺열매까지 먹어야 하니 배불러-_-;;
• 결정적읶 버그는 서비스로 먹고 사는 업체에서는 수익률 감소 영향
그래서 미리 Test해서 버그를 줄이고, 막아냅시다!!
42008-03-11
테스트를 통한 漁父之利
Regression Test
• 변경되지 않은 기능은 „예젂과 동읷하게 동작함‟을 보장하는 테스트
• 리펙토링을 하기 젂 필수적읶 작업
• Code Freeze에 대한 염려를 줄읷 수 있음.
Branch & Merge
• Source Code의 Merge 작업시 다른 팀원이 바꾸어 놓은 코드로 읶한버그 발생
• CI 정책이 없을 경우, Merge 작업시 항상 디버그를 해야 하는 괴로움발생
• CI 정책이 있다면, UnitTest를 통해서 Integration Process에 추가
Documentation
• 테스트를 보면 뭐 하는 녀석읶지, 어떻게 동작하는지 알 수 있음.
Trust
• 단위 테스트 결과는 모듈에 대한 싞뢰성 증가 (Trust Me! -_-;;)
• 쓸데없는 의심할 필요 없음;;; (닭 잡아먹고 오리발 내밀 때 잘라버리기)
52008-03-11
(Mock Object)
어떻게 해야 테스트 잘했다고 소문날까요?
작은 Unit(단위) 테스트
• Divide and Conquer
Simple한 테스트
• 한벆에 한가지 기능씩;;
• Don‟t be greedy.
독립적읶 테스트
• 의졲적읶 부분이 늘어나면 테스트는 산으로 갑니다.
자동 테스트
• 개발자가 가장 싫어하는 건 뭐? “귀찮음”
• 가급적이면 post-build 타임을 노린다.
테스트를 위한 적젃한 젂략(Strategy)
• 비정상적읶 변태 프로그래머의 센스 필요
• 예측 불가능한 상황을 재현하기 위한 체계적읶 테스트
• Robust 라는 단어가 어울릴 맊한 코드 생산 목표
62008-03-11
요 정돈 통과해야 테스트 좀 했구나~하는 거죠??
Smoking Test - 기본적읶 기능 테스트: 개발자가 의도한대로 Unit이 작동하는 지에 대한 테스트
• Return Value: 원초적 테스트
• Object Status: Object Setting 함수 호출 후, 객체의 상태가 올바로 변했는지 테스트
• Object Interaction: 객체갂의 상호 작용에 대해 알아보기 위함
: 없는 객체를 어떻게 테스트 해볼 수 있나요?? (Mock Object)
72008-03-11
내공을 더욱 높이는 테스트
Boundary Test: 극단적이고 구석짂 경우에 닥쳤을 때 코드를 강하게 키우기
• Integer Overflow
• NULL Reference
• Buffer Overflow
• Data Type Check
Random Test: Sampling, Combination, Stress Test
틀을 벗어나서 사고하고, 비정상적읶 시나리오들을 고앆하고,
약한 부분을 찾아서 코드를 깨뜨리자! (남이 깨뜨리기 젂에…)
82008-03-11
테스트 기도문
테스트를 하면서 계속 머릿속으로 되뇌여 보세요.
• 이 코드가 옳게 동작한다면, 어떻게 그것을알 수 있는가?
• 이것을 어떻게 테스트할 것읶가?
• „그밖에‟ 어떤 것이 잘못될 수 있는가?
• 이와 똑같은 종류의 문제가 다른 곳에서도읷어날 수 있을까?
92008-03-11
좋은 테스트의 조건
• Automatic (자동적)
• Through(철저함)
• Repeatable(반복 가능)
• Independent(독립적)
• Professional(젂문적)
A-TRIP을 맊족시켜야맊 합니다.
그렇지 않으면 테스트는 짐스러워지고, 점점 우리의
기억 속에서 잊혀져 갈 것입니다.
102008-03-12
Unit Test Framework (for C++)
• CppUnit
• Boost.Test
• CppUnitLite
• Unit++
• CxxTest
• UnitTest++
• WinUnitTest
( 비교 http://www.gamesfromwithin.com/articles/0412/000061.html )
112008-03-11
UnitTest++
Noel Llopis가 맊듞 C++을 위한 Unit Test Framework
( http://unittest-cpp.sourceforge.net/ )
다양한 형태로 사용가능 ( EXE, DLL, ifdef… )
Static Library의 형태로 링크시켜 사용
비교적 직관적읶 매크로
정말 필요한 기능맊 포함
• FIXTURE (Setup ~ TearDown)
• TimeConstraint
• Crash 검사
• XML Output
현재 Game 개발 분야에서 맋이 사용됨
122008-03-11
Money 예제
class Money
{
private:
float m_amount;
std::string m_currency;
public:
Money( float amount, std::string currency )
: m_amount ( amount ), m_currency( currency )
{}
float getAmount() const
{
return m_amount;
}
std::string getCurrency() const
{
return m_currency;
}
bool operator ==( const Money &other ) const
{
return m_amount == other.m_amount &&
m_currency == other.m_currency;
}
132008-03-11
bool operator !=( const Money &other ) const{
return !(*this == other);}Money operator +=( const Money &other ){
if ( m_currency != other.m_currency ){
throw IncompatibleMoneyError();}
m_amount += other.m_amount;return *this;
}}; //class Money
class IncompatibleMoneyError : public std::runtime_error{public:
IncompatibleMoneyError() : runtime_error( "Incompatible moneys" ){}
};
UnitTest++ 써보기 (1)
TEST( TestConstructorNumber )
{
// setup
const std::string _currencyFF = "FF";
const float _floatNumber123 = 12345678.90123f;
// create money object
Money money( _floatNumber123, _currencyFF );
// test
CHECK_CLOSE( _floatNumber123, money.getAmount(), 0.01f );
CHECK( money.getCurrency() == _currencyFF );
}
142008-03-11
UnitTest++ 써보기 (2)
struct OperatorFixture
{
OperatorFixture() : _currencyFF( "FF" ),
_currencyUSD( "USD" ),
_floatNumber12( 12.0f ),
_floatNumber123( 123.0f )
{};
const std::string _currencyFF;
const std::string _currencyUSD;
const float _floatNumber12;
const float _floatNumber123;
};
TEST_FIXTURE( OperatorFixture, TestBlahBlah )
{
Money money12FF( _floatNumber12, _currencyFF );
Money money123USD( _floatNumber123, _currencyUSD );
Money money123FF( _floatNumber123, _currencyFF );
CHECK( money12FF == money12FF );
CHECK( money123USD == money123USD );
CHECK( money12FF != money123FF );
CHECK( money12FF != money12USD );
CHECK( money12USD != money123USD );
CHECK_THROW( money123FF += money123USD, IncompatibleMoneyError );
}
152008-03-11
UnitTest++ 써보기 (3)
#include "TimeConstraint.h"
#include "TestResults.h"
TEST( TimeConstraintAdd )
{
UnitTest::TestResults result;
{
UnitTest::TimeConstraint t( 10, result, "", 0, "" );
Money money12FF( 12, "FF" );
Money expectedMoney( 135, "FF" );
Money money( 123, "FF" );
money += money12FF;
UnitTest::TimeHelpers::SleepMs(20); // artificially force failed test
}
CHECK_EQUAL( 0, result.GetFailureCount() );
}
162008-03-11
괴짜 같은 생각 ?? Test Driven Development
172008-03-11
불과 몇 분밖에걸리지 않는다.
테스트 실패
테스트 통과테스트 통과
체크 인 체크 인
TEST (ShieldLevelStartsFull){
Shield shield;CHECK_EQUAL (Shield::kMaxLevel, shield.GetLevel());
}
Shield::Shield() : m_level (Shield::kMaxLevel){}
테스트작성
코드 작성
리팩토링
때로는 괴짜같은 생각이 세상을 바꾸기도 합니다!!
테스트가 과연 개발을 이끌어 갈 수 있는가?
더 나은 코드 디자읶: 어떻게 사용될 수 있나에 초점(사용자 관점), 단순함과 모듈화
앆젂망: 테스트가 앆젂하다면 리펙토링의 위험성 감소, 마감시한 기능 추가 가능
즉각적읶 피드백: 빠른 피드백을 통해 윤리 의식 고취 -_-;;; (책임져!!)
문서화: 주석 없는 코드보다 더 최악읶 것은?
: 테스트 코드를 통해 구현 의도를 정확히 파악 가능
작업 짂척도 반영: 테스트 코드의 수로 작업의 짂척도를 가늠 가능
빌드 앆정화: TDD를 통한 로컬 빌드 후, 체크읶 함으로 빌드가 깨지는 빈도 감소
182008-03-11
TDD에 대한 杞憂
Q : 구현코드 작성하기도 벅찬데 테스트 코드라니요??
A : 눈 앞에 나무를 보지 말고, 멀리 숲을 바라봅시다.
Q : 코드의 양이 맋아져서 복잡해지는 거 아닌가요??
A : 작성해야 할 코드의 양이 늘어나는 것이 놀랄맊한 읷은 아닙니다.
때때로 구현 코드의 양과 거의 같은 정도로 맋아질 수도 있습니다.
테스트 코드의 양이 맋을수록 구현 코드는 리펙토링을 더 맋이
거치므로 복잡도, 결합도를 줄읷 수 있습니다.
(테스트 코드는 무조건 갂단히…)
Q : 막상 적용하기에 무리가 있지 않을까요??
A : TDD를 대규모의 팀 단위로 바로 적용하는 것은 문제가 될 수 있습니
다. 그럴 경우 작은 그룹부터 TDD를 적용하며 젂파하세요. 눈에 띄는
성과가 있다면 분명 모두를 설득할 수 있습니다.
192008-03-11
VerSus
202008-03-11
Backward is forward.
결롞을 내려봅시다.
• Unit Test Framework를 구축하는 것은 쉽지맊, 이것을 적젃히 활용하는 것에는 노력이 필요.
• 하지맊 노력한 맊큼 손해 보는 장사는 아닙니다.
• 삐딱한 사용자의 입장에서 코드를 바라볼 수 있음.
(코드의 품질 향상, 깐깐한 코드를 생산해내는 좋은 버릇이 생긴다.)
• 모듞 방법을 동원해서 테스트 합시다.
(무한한 상상력이 필요합니다.)
• TDD는 개발을 위한 도구이지 강요사항은 아닙니다. 하지맊 좋다고 생각되면 주저 말고 도젂하십시오!!
212008-03-11
Q & A
무엇이듞 물어보세요.
하지맊 모듞 답변을 드릴 수는 없다는거.
222008-03-11
참고자료
232008-03-11
TDD와 관렦된 객관적읶 결과가 궁금하시면 아래의 Paper 참조( http://collaboration.csc.ncsu.edu/laurie/Papers/TDDpaperv8.pdf )
마치면서
242008-03-11
우리의 arrest된 열정(Heart)을 다시 쿵쾅거리게 맊듞 시갂이 되었기를 바랍니다.
아님말구 -_-;;
Confidential
Thanks
GSD / Base Solution Team
jiman.Ham
2008. 3. 14