작성: ospace.tistory.com (ospace114@empal.com)
여기는 일부러 에러를 반든 코드를 작성하였다. 테스트하면 에러가 발생할 것이다. 중간에 코멘드를 달겠지만, 에러난 부분에 대해서 직접 에러를 찾는것도 괜찮을 것 같다. 참고로 아래 코드 VC++에서 테스트되었다.
테스트 작성하기
TEST 매크로
TEST 매크로는 ()안에 있는 이름으로 UnitText++ 테스트 목록에 자동으로 등록하고 RunAllTests()에 의해서 자동으로 테스트 실행한다.
TEST( TestName )
{
CHECK( true ); // 성공 테스트
}
TEST_FIXTURE 매크로
TEST 매크로와 비슷하지만 첫번째 인자는 Fixture 객체로 해당 객체에 안에 있는 멤버 데이터를 초기화하고 바로 사용할 수 있다. 그리고 테스트가 끝나면 자동으로 해제된다. 즉, 자동으로 생성자와 소멸자를 호출해서 테스트에 필요한 데이터를 바로 사용할 수 있다. 두번째 인자는 TEST 매크로의 인자와 같이 UnitTest++에 등록되는 이름이다.
struct AFixture
{
AFixtrue() : _data("some data") {}
const std::string _data;
};
TEST_FIXTURE( AFixture, TestName )
{
CHECK( "some data" == _data );
}
SUITE 매크로
TEST 혹은 TEST_FIXTURE 매크로에 의해 등록되는 테스트들에 대한 그룹을 생성한다.
SUITE( SuiteName )
{
TEST( TestName1 )
{
}
TEST( TestName2 )
{
}
}
테스트 매크로
CHECK( bool )
bool 체크에서 true이어야 통과
CHECK_EQUAL( val1, val2 )
val1과 val2가 동일한 값이어야 통과
CHECK_CLOSE( val1, val2, diff )
val1과 val2 값이 차이가 diff보다 작거나 같아야 통과
CHECK_ARRAY_EQUAL( arr1, arr2, arr_size )
두 배열 값이 arr_size 개수 만큼 비교하여 동일한 값이어야 통과
CHECK_ARRAY_CLOSE( arr1, arr2, arr_size, diff)
투 배열 값이 arr_size 개수 만큼 차이를 계산하여 그 차이가 diff보다 작거나 같으면 통과
CHECK_THROW( val, exception_name )
val이 예외가 발생하고 그 값이 exception_name과 동일해야 통과
테스트 코드
#include "Money.h"
#include "UnitTest++.h"
struct ConstructorFixture
{
ConstructorFixture()
: _currencyFF( "FF" )
, _floatNumber123( 12345678.90123f )
{}
const std::string _currencyFF;
const float _floatNumber123;
};
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 );
}
TEST( TestConstructorCurrency )
{
// setup
const std::string _currencyFF = "FF";
const float _floatNumber123 = 12345678.90123f;
// create money object
Money money( _floatNumber123, _currencyFF );
// test
CHECK( money.getCurrency() == _currencyFF );
}
// 이는 앞의 두개 테스트를 FIXTURE를 이용해서 코드량을 줄임
TEST_FIXTURE( ConstructorFixture, TestConstructorNumber2 )
{
Money money( _floatNumber123, _currencyFF );
CHECK_CLOSE( _floatNumber123, money.getAmount(), 0.01f );
}
TEST_FIXTURE( ConstructorFixture, TestConstructorCurrency2 )
{
Money money( _floatNumber123, _currencyFF );
CHECK( money.getCurrency() == _currencyFF );
}
TEST( TestAdd )
{
// setup
Money money12FF( 12, "FF" );
Money expectedMoney( 135, "FF" );
// operate
Money money(123, "FF" );
money += money12FF;
// test
CHCECK_EQUAL( expectedMoney.getAmount(), money.getAmount() );
CHECK( money.getAmount() == expectedMoney.getAmount() );
}
TEST( TestIncompatibleMoneyError )
{
// test
CHECK_THROW( throw IncompatibleMoneyError(), IncompatibleMoneyError );
}
TEST_FIXTURE( ConstructorFixture, TestAddThrow )
{
// setup
Money money12FF( _floatNumber12, _currencyFF );
Moeny money123USD( _floatNumber123, _currencyUSD );
// test
CHECK_THROW( moeny12FF += money123USD, IncompatibleMoneyError );
}
TEST( TimeConstaintAdd )
{
UnitTest::TestResult result;
{
UnitTest::TimeConstraint t (10, TestDetails("", "", __FILE__, __LINE__));
Money money12FF( 12, "FF" );
Money expectedMoney( 135, "FF" );
Money money( 123, "FF" );
money += money12FF;
UnitTest::timeHelpers::SleepMs(20);
}
// test
CHECK_EQUAL (0, result.GetFailureCount());
CHECK_EQUAL (0, UnitTest::CurrentTest::Results()->GetFailureCount());
}
테스트 대상이되는 코드
//Money.h
#pragma once
#include <string>
#include <stdexcept>
class IncompatibleMoneyErr : public std::runtime_error
{
public:
IncompatibleMoneyError() : runtime_error("Incompatible moneys") {}
};
class Money
{
private:
float m_amount;
std::string m_currency;
Money(float amont, std::string currency) : m_amount(amount) {}
float getAmount() const {
return m_amount;
}
std::string getCurrency() const
{
return "bogus";
}
bool operator ==( const Moeny &other ) const
{
return m_amount == other.m_ammount || m_currency == other.m_currency;
}
bool operator !=( cosnt Money &other) const
{
return !(this == other);
}
Money &operator +=( const Money *other )
{
m_amount = 9876.54321f
return *this;
}
}
Money 생성자에서 m_currency 최기화 필요
m_currency( currency )
getCurrency() 멤버 함수에서 반환 값은 m_currency임
return m_currency;
operator ==()에서의 비교는 AND 연산이어야 함
return m_amount == other.m_amount && m_currency == other.m_currency;
operation !=()에서 비교 대상이 this가 아니고 *this이어야 함
return !(*this == other);
operation +=()에서 더하기 연산이 필요
m_amount += other.m_amount;
operation +=()에서 currency가 맞지 않는 부분 예외 처리
if( m_currency != other.m_currency ) throw IncompatibleMoneyError();
참조
[1] Matthew Granic, Money a step by step example for Visual Studio .NET 2005, http://unittest-cpp.sourceforge.net/money_tutorial/, Medical Simulation Corporation®
'4.개발 및 운영 환경' 카테고리의 다른 글
log4cxx 및 apr 설치 및 빌드 환경 구성 (0) | 2012.08.16 |
---|---|
비동기 테스트 (0) | 2012.08.16 |
CUNIT 테스팅 (0) | 2012.08.16 |
Windows에서 지워지지 않은 파일 삭제하기 (0) | 2012.01.09 |
Xming에서 Xwindow 설정과 eclipse 실행 (0) | 2012.01.09 |