이번 리뉴얼 목표에 테스트 드리븐을 적용하는 것도 포함되어있습니다. 여러 단위 테스트 라이브러리가 있는데 이전에도 사용해본적 있고 또 많이 사용되고 있는 UnitTest++를 적용하기로 했습니다. 구글의 GTest에도 눈이 갔지만 왠지 UnitTest++가 더 끌리더군요. 

UnitTest++ 프로젝트를 추가한 모습

UnitTest++ 적용법을 간단히 적어보겠습니다. 일단 최신 버전 UnitTest++를 다운 받습니다.


압축을 풀면 대략 밑의 화면 처럼 나옵니다. 솔루션 파일은 2003과 2005만 있는데 2008의 경우 2005 솔루션파일을 변환하여 바로 사용 가능합니다. 2010은 어떨지 모르겠네요;;;


이제 빌드를 해줍니다. 그러면 Lib 파일이 생성 됩니다. UnitTest++를 사용하기 위해 필요한것은 이 Lib파일과 src 폴더 안의 헤더들 뿐입니다. 관리하기 편하게 추가할 프로젝트 폴더에 UnitTest 하위 폴더를 하나 만들어서 그곳에 다 넣어줍니다. 저의 경우 UnitTest 하위 폴더를 만들어서 Include / Lib 폴더에 각각 헤더와 Lib 파일을 넣어뒀습니다.

 \Lib
 \Include
 \Include\Posix
 \Include\tests
 \Include\Win32

다음으로 UnitTest++ 프로젝트를 추가합니다. UnitTest++는 단순히 테스트 결과를 출력해주는 프로젝트인 만큼 Win32 콘솔 프로그램 프로젝트만으로 충분합니다. 


이 프로젝트에 UnitTest++.h와 UnitTest++.lib(이름이 좀 다를수 있습니다) 를 추가 하는 것으로 UnitTest++를 사용하기 위한 준비가 끝납니다.

#include "Include\UnitTest++.h"
#pragma comment ( lib, "UnitTest++.lib")
int main(int argc, char const *argv[])
{
	return UnitTest::RunAllTests();
}

이제 단위 테스트를 수행할수 있는 환경이 조성되었습니다. EVE 프로젝트 같은 경우 엔진단의 EVE가 정적 라이브러리로 작성 되어 있기때문에 UnitTest 프로젝트에서 단순히 EVE의 Lib와 헤더만 불러오면 EVE 프로젝트에 대한 단위 테스트를 수행 할수 있습니다. 얼마전에 추가한 Quaternion 타입에 대한 단위 테스트 예제를 보여드리겠습니다. 여러 연산 함수들의 결과값이 DirectX 함수들을 사용한 값 처럼 정확하게 출력되는지 확인하는 코드입니다.

SUITE( evQuaternionTest )
{
	TEST( evQuaternion_FromAngleAxis )
	{
		D3DXQUATERNION qRot_DX;
		ev_CQuaternion qRot_EV;

		D3DXQuaternionRotationAxis( &qRot_DX, &D3DXVECTOR3( 1, 0, 0 ), 10 );
		qRot_EV.FromAngleAxis( 10, ev_CVector3::UNIT_X );
		CHECK_CLOSE( qRot_DX.x, qRot_EV.x, 0.00001f );

		D3DXQuaternionRotationAxis( &qRot_DX, &D3DXVECTOR3( 0, 1, 0 ), 20 );
		qRot_EV.FromAngleAxis( 20, ev_CVector3::UNIT_Y );
		CHECK_CLOSE( qRot_DX.y, qRot_EV.y, 0.00001f );

		D3DXQuaternionRotationAxis( &qRot_DX, &D3DXVECTOR3( 0, 0, 1 ), 50 );
		qRot_EV.FromAngleAxis( 50, ev_CVector3::UNIT_Z );
		CHECK_CLOSE( qRot_DX.z, qRot_EV.z, 0.00001f );
	}

	TEST( evQuaternion_FromRotationMatrix )
	{
		D3DXMATRIX matRot;
		D3DXMatrixRotationX( &matRot, 30 );

		D3DXQUATERNION qRot_DX;
		ev_CQuaternion qRot_EV;

		D3DXQuaternionRotationMatrix( &qRot_DX, &matRot );
		qRot_EV.FromRotationMatrix( evConToEVMat( matRot ) );
		
		CHECK_CLOSE( qRot_DX.x, qRot_EV.x, 0.00001f );
		CHECK_CLOSE( qRot_DX.y, qRot_EV.y, 0.00001f );
		CHECK_CLOSE( qRot_DX.z, qRot_EV.z, 0.00001f );
		CHECK_CLOSE( qRot_DX.w, qRot_EV.w, 0.00001f );
	}

	TEST( evQuaternion_FromYawPitchRoll )
	{
		D3DXQUATERNION qRot_DX;
		ev_CQuaternion qRot_EV;

		D3DXQuaternionRotationYawPitchRoll( &qRot_DX, 10, -30, 50 );
		qRot_EV.FromYawPitchRoll( 10, -30, 50 );

		CHECK_CLOSE( qRot_DX.x, qRot_EV.x, 0.00001f );
		CHECK_CLOSE( qRot_DX.y, qRot_EV.y, 0.00001f );
		CHECK_CLOSE( qRot_DX.z, qRot_EV.z, 0.00001f );
		CHECK_CLOSE( qRot_DX.w, qRot_EV.w, 0.00001f );
	}
}
테스트가 정상적으로 통과 되면 밑의 스샷 처럼 출력되어 나옵니다. 실패하면 실패한 테스트의 이름과 이유가 같이 출력됩니다.


+ Recent posts