0
C++ 프로젝트에 단위 테스트 도입하기<br />최우영<br />위메이드 엔터테인먼트<br />
강연자 소개<br />최우영<br />(주)위메이드 엔터테인먼트<br />신규 게임 개발팀 -서버 파트<br />(주)라온 엔터테인먼트<br />테일즈런너<br />신규 게임 개발<br />
Test?<br />
통합 테스트 VS 단위 테스트<br />통합 테스트<br />둘 이상의 모듈을 하나의 그룹으로 테스트 하는 것<br />소프트웨어에 기대되는 결과를 확인 하는 것.<br />많은 단위들을 실행<br />단위 테스트<br...
단위 테스트란<br />다른 코드를 호출한 후 몇 가지 가정이 성립하는지 검사하는 코드<br />여기서 '단위(unit)'란 메서드나 함수를 의미<br />X + Y = Z ?<br />
좋은 단위 테스트<br />자동화<br />반복 실행<br />쉬운 구현<br />쉬운 실행<br />빠른 속도<br />로직 없는 테스트<br />
테스트 프레임워크<br />CppUnit, UnitTest++, TUT, …<br />사용하기 쉽고 신뢰할 수 있는 GoogleTest<br />http://code.google.com/p/googletest/<br /...
Gtest 사용하기<br />gtest라이브러리 다운로드<br />gtest.h파일 include<br />라이브러리 빌드 후 lib 파일 링크<br />#include <gtestgtest.h><br />#pragma...
테스트 문법의 기본<br />ASSERT_TRUE( ACTUAL )ASSERT_FALSE( ACTUAL )<br />ASSERT_EQ( EXPECTED, ACTUAL )ASSERT_NE( EXPECTED, ACTUAL ...
테스트 작성<br />TEST( test_suite, test_case)<br />{<br />	...<br />ASSERT_XXX()<br />	...<br />}<br />
간단한 테스트의 작성<br />swap() 함수 구현<br />X, Y 를 인자로 받고 X = Y, Y = X 로 교환<br />
테스트 파일 생성<br />Ex) Swap_Test.cpp<br />테스트스위트, 케이스 이름 결정<br />보수의 용이성을 위해 테스트 이름을 정한다<br />테스트 스위트는 테스트 카테고리<br />케이스 이름은 세...
#include <gtestgtest.h> <br />TEST( Swap_Test, Swap_True){<br />}<br />[==========] Running 1 test from 1 test case.<br />...
#include <gtestgtest.h> <br />TEST( Swap_Test, Swap_True ){<br />int x = 30;<br />int y = 15;<br />swap( x, y );<br />ASSE...
#include <gtestgtest.h> <br />void swap(int& x, int& y){}<br />TEST( Swap_Test, Swap_True ){<br />int x = 30;<br />int y =...
[==========]Running 1 test from 1 test case.<br />[----------]Global test environment set-up.<br />[----------] 1 test fro...
[==========]Running 1 test from 1 test case.<br />[----------]Global test environment set-up.<br />[----------] 1 test fro...
[==========] Running 1 test from 1 test case.<br />[----------] Global test environment set-up.<br />[----------] 1 test f...
#include <gtestgtest.h> <br />void swap(int& x, int& y){<br />int t = x;<br />	y = x;<br />	x = t;<br />}<br />TEST( Swap_...
[==========] Running 1 test from 1 test case.<br />[----------] Global test environment set-up.<br />[----------] 1 test f...
의존성 제거<br />클래스 간 복합적인 관계 의존성 존재<br />테스트 저해 설계 : 파일, 스레드, 통신등 외부 의존물을 사용<br />통합테스트 => 단위 테스트 <br />
패킷 변환<br />테스트 대상<br />통신 담당<br />
...<br />TEST( CPacketHandler, ProcessPacketSuccessWithItemBuyReq){<br />CPacketHandlerPacketHandler;<br />	MSG_ITEM_BUY_R...
class CPacketHandler<br />{<br />CConnectionManager*	m_pConnectionManager;<br />CPacketParser*		m_pPacketParser;<br />publ...
class CPacketParser<br />{<br />public:<br />	......<br />MSG_BASE* ParsePacket( const char* pBuf, size_tpacketSize ) <br ...
class CConnectionManager<br />{<br />CSendQueue* m_pSendQueue;<br />public:<br />	......<br />void SendPacket( MSG_BASE* p...
class CConnectionManager<br />{<br />CSendQueue* m_pSendQueue;<br />public:<br />	......<br />void SendPacket( MSG_BASE* p...
스텁(Stub)<br />외부 의존물을 대신하기 위해 간접 계층 추가<br />
간접 계층<br />외부 의존물에 접근하기 위해 인터페이스 추가<br />
class CPacketHandler<br />{<br />IConnectionManager*	m_pConnectionManager;<br />CPacketParser*		m_pPacketParser;<br />publ...
스텁 주입하기<br />생성자<br />get, set 프로퍼티<br />매개변수<br />추상 팩토리<br />
생성자 주입<br />장점<br />테스트 코드의 가독성 향상<br />해당 매개 변수가 필수임을 알림<br />단점<br />상호 참조의 경우 생성 문제<br />매개 변수의 개수가 늘어날 수록 가독성, 관리용이성 악...
class CPacketHandler<br />{<br />IConnectionManager* m_pConnectionManager;<br />	...<br />public:<br />SetConnectionManage...
그 외 대표적 방법들<br />매개변수 전달<br />함수를 호출할 때 함께 의존물을 넣어준다.<br />추상 팩토리<br />실제 객체와 스텁을 생성하는 팩토리를 생성하는 추상 팩토리를 생성<br />
캡슐화 문제<br />테스트 용이성을 높이기 위한 방법<br />Public<br />상속<br />Friend<br />조건부 컴파일(#ifdef)<br />상용 프레임워크<br />
픽스쳐<br />class fixture_name;<br />TEST_F( fixture_name, case_name)<br />{<br />...<br />...// Some Tests<br />ASSERT_XXX()...
class fixture_name : public testing::Test<br />{<br />	void	SetUp();<br />void	TearDown();<br />};<br />TEST_F( fixture_na...
목 객체(Mock Object)<br />단위 테스트의 통과, 실패를 판단하는 가짜 객체<br />하나의 테스트에 하나의 목 객체 사용<br />
스텁 vs 목<br />스텁: 객체의 대체제. 테스트가 가능하도록 의존물을 없애는 것<br />목: 테스트의 통과, 실패를 검증<br />
목 객체의 사용<br />CPacketHandler가 IConnectionManager::SendPacket() 메서드를 호출하는지 확인<br />ConnectionManager의 인터페이스를 추출, 스텁으로 교체.<b...
class FakeConnectionManager: public IConnectionManager{<br />public:<br />intm_nCalled;<br />MSG_BASE* m_pPacket;<br />	.....
격리 프레임워크(Isolation Framework)<br />목과 스텁 객체를 쉽게 생성할 수 있게 해주는 API의 모음<br />테스트의 반복 작성시 도움을 받을 수 있다.<br />예상값(기대값)의 측정<br />...
Google Mock 사용법<br />목 오브젝트 생성<br />class Impl{<br />public:<br />virtual void	SetPos(float x, float y);<br />virtual floa...
 함수 호출 측정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br />EXPECT_CALL( impl, GetPos() );<br />	EXPECT...
 함수 호출 횟수 측정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br />EXPECT_CALL( impl, GetPos() )<br />	.Tim...
리턴값 지정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br />	//  ON_CALL( impl, GetPos() )<br />EXPECT_CAL...
Class FakeConnectionManager: public IConnectionManager{<br />public:<br />intm_nCalled;<br />MSG_BASE* m_pPacket;<br />	.....
class FakeConnectionManager: public IConnectionManager{<br />public:<br />MOCK_METHOD1( SendPakcet, void(MSG_BASE* pPacket...
팁<br />목 객체는 테스트 당 1개<br />목 객체, 테스트 객체를 제외한 모든 의존물은Stub으로 대체<br />ASSERT는 가급적 테스트 당 1개<br />목 객체를 재사용 : 목 객체 내부에 ASSERT 삽...
감사합니다<br />whoo24@gmail.com<br />Twitter: whoo24<br />Blog : http://blog.wychoe.net<br />
Upcoming SlideShare
Loading in...5
×

C++ 프로젝트에 단위 테스트 도입하기

6,918

Published on

Published in: Travel, Business, Technology
0 Comments
26 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,918
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
108
Comments
0
Likes
26
Embeds 0
No embeds

No notes for slide

Transcript of "C++ 프로젝트에 단위 테스트 도입하기"

  1. 1. C++ 프로젝트에 단위 테스트 도입하기<br />최우영<br />위메이드 엔터테인먼트<br />
  2. 2. 강연자 소개<br />최우영<br />(주)위메이드 엔터테인먼트<br />신규 게임 개발팀 -서버 파트<br />(주)라온 엔터테인먼트<br />테일즈런너<br />신규 게임 개발<br />
  3. 3. Test?<br />
  4. 4. 통합 테스트 VS 단위 테스트<br />통합 테스트<br />둘 이상의 모듈을 하나의 그룹으로 테스트 하는 것<br />소프트웨어에 기대되는 결과를 확인 하는 것.<br />많은 단위들을 실행<br />단위 테스트<br />단일 단위를 분리하여 실행하는 테스트<br />
  5. 5. 단위 테스트란<br />다른 코드를 호출한 후 몇 가지 가정이 성립하는지 검사하는 코드<br />여기서 '단위(unit)'란 메서드나 함수를 의미<br />X + Y = Z ?<br />
  6. 6. 좋은 단위 테스트<br />자동화<br />반복 실행<br />쉬운 구현<br />쉬운 실행<br />빠른 속도<br />로직 없는 테스트<br />
  7. 7. 테스트 프레임워크<br />CppUnit, UnitTest++, TUT, …<br />사용하기 쉽고 신뢰할 수 있는 GoogleTest<br />http://code.google.com/p/googletest/<br />구글의 제품에 사용 중<br />Chromium, Protocol Buffers, … 등등<br />
  8. 8. Gtest 사용하기<br />gtest라이브러리 다운로드<br />gtest.h파일 include<br />라이브러리 빌드 후 lib 파일 링크<br />#include <gtestgtest.h><br />#pragma comment(lib, “gtest.lib”)<br />int main(intargc, _TCHAR* argv[])<br />{<br /> ::testing::InitGoogleTest(&argc, argv);<br /> return RUN_ALL_TESTS();<br />}<br />
  9. 9. 테스트 문법의 기본<br />ASSERT_TRUE( ACTUAL )ASSERT_FALSE( ACTUAL )<br />ASSERT_EQ( EXPECTED, ACTUAL )ASSERT_NE( EXPECTED, ACTUAL )<br />ASSERT_FLOAT_EQ( EXPECTED, ACTUAL )<br />ASSERT_STREQ( EXPECTED, ACTUAL)<br />
  10. 10. 테스트 작성<br />TEST( test_suite, test_case)<br />{<br /> ...<br />ASSERT_XXX()<br /> ...<br />}<br />
  11. 11. 간단한 테스트의 작성<br />swap() 함수 구현<br />X, Y 를 인자로 받고 X = Y, Y = X 로 교환<br />
  12. 12. 테스트 파일 생성<br />Ex) Swap_Test.cpp<br />테스트스위트, 케이스 이름 결정<br />보수의 용이성을 위해 테스트 이름을 정한다<br />테스트 스위트는 테스트 카테고리<br />케이스 이름은 세부적인 테스트를 나타낸다<br />
  13. 13. #include <gtestgtest.h> <br />TEST( Swap_Test, Swap_True){<br />}<br />[==========] Running 1 test from 1 test case.<br />[----------] Global test environment set-up.<br />[----------] 1 test from Swap_Test<br />[ RUN ] Swap_Test.Swap_True<br />[ OK ] Swap_Test.Swap_True (0 ms)<br />[----------] 1 test from Swap_Test (0 ms total)<br />[----------] Global test environment tear-down<br />[==========] 1 test from 1 test case ran. (0 ms total)<br />[ PASSED ] 1 test.<br />
  14. 14. #include <gtestgtest.h> <br />TEST( Swap_Test, Swap_True ){<br />int x = 30;<br />int y = 15;<br />swap( x, y );<br />ASSERT_EQ( 15, x ) << "x must be 15";<br />ASSERT_EQ( 30, y ) << "y must be 30";<br />}<br />build => fail<br />존재하지 않는 함수 호출로 빌드실패<br />
  15. 15. #include <gtestgtest.h> <br />void swap(int& x, int& y){}<br />TEST( Swap_Test, Swap_True ){<br />int x = 30;<br />int y = 15;<br /> swap( x, y );<br /> ASSERT_EQ( 15, x ) << "x must be 15";<br /> ASSERT_EQ( 30, y ) << "y must be 30";<br />}<br />build => successtest => failure<br />빌드 성공, 테스트 실패<br />
  16. 16. [==========]Running 1 test from 1 test case.<br />[----------]Global test environment set-up.<br />[----------] 1 test from Swap_Test<br />[ RUN ]Swap_Test.Swap_True<br />c:....Swap_Test.cpp(124): error: Value of: x<br /> Actual: 30<br />Expected: 15<br />x must be 15<br />[ FAILED ] Swap_Test.Swap_True (0 ms)<br />[----------]1 test from Swap_Test (0 ms total)<br />[----------]Global test environment tear-down<br />[==========]1 test from 1 test case ran. (0 ms total)<br />[ PASSED ] 0 tests.<br />[ FAILED ] 1 test, listed below:<br />[ FAILED ] Swap_Test.Swap_True<br /> 1 FAILED TEST<br />
  17. 17. [==========]Running 1 test from 1 test case.<br />[----------]Global test environment set-up.<br />[----------] 1 test from Swap_Test<br />[ RUN ]Swap_Test.Swap_True<br />c:....Swap_Test.cpp(124): error: Value of: x<br /> Actual: 30<br />Expected: 15<br />x must be 15<br />[ FAILED ] Swap_Test.Swap_True (0 ms)<br />[----------]1 test from Swap_Test (0 ms total)<br />[----------]Global test environment tear-down<br />[==========]1 test from 1 test case ran. (0 ms total)<br />[ PASSED ] 0 tests.<br />[ FAILED ] 1 test, listed below:<br />[ FAILED ] Swap_Test.Swap_True<br /> 1 FAILED TEST<br />
  18. 18. [==========] Running 1 test from 1 test case.<br />[----------] Global test environment set-up.<br />[----------] 1 test from Swap_Test<br />[ RUN ] Swap_Test.Swap_True<br />c:....Swap_Test.cpp(124): error: Value of: x<br /> Actual: 30<br />Expected: 15<br />x must be 15<br />[ FAILED ] Swap_Test.Swap_True (0 ms)<br />[----------] 1 test from Swap_Test (0 ms total)<br />[----------] Global test environment tear-down<br />[==========] 1 test from 1 test case ran. (0 ms total)<br />[ PASSED ] 0 tests.<br />[ FAILED ] 1 test, listed below:<br />[ FAILED ] Swap_Test.Swap_True<br /> 1 FAILED TEST<br />…<br />ASSERT_EQ( 15, x ) << "x must be 15“;<br />…<br />
  19. 19. #include <gtestgtest.h> <br />void swap(int& x, int& y){<br />int t = x;<br /> y = x;<br /> x = t;<br />}<br />TEST( Swap_Test, Swap_True ){<br />int x = 30;<br />int y = 15;<br /> swap( x, y );<br /> ASSERT_EQ( 15, x ) << "x must be 15";<br /> ASSERT_EQ( 30, y ) << "y must be 30";<br />}<br />build => successtest => pass<br />테스트 통과<br />
  20. 20. [==========] Running 1 test from 1 test case.<br />[----------] Global test environment set-up.<br />[----------] 1 test from Swap_Test<br />[ RUN ]Swap_Test.Swap_True<br />[ OK ]Swap_Test.Swap_True (0 ms)<br />[----------] 1 test from Swap_Test (0 ms total)<br />[----------] Global test environment tear-down<br />[==========] 1 test from 1 test case ran. (0 ms total)<br />[ PASSED ] 1 test.<br />
  21. 21. 의존성 제거<br />클래스 간 복합적인 관계 의존성 존재<br />테스트 저해 설계 : 파일, 스레드, 통신등 외부 의존물을 사용<br />통합테스트 => 단위 테스트 <br />
  22. 22. 패킷 변환<br />테스트 대상<br />통신 담당<br />
  23. 23. ...<br />TEST( CPacketHandler, ProcessPacketSuccessWithItemBuyReq){<br />CPacketHandlerPacketHandler;<br /> MSG_ITEM_BUY_REQ ItemBuyReq;<br />boolbRet = PacketHandler.ProcessPacket( &ItemBuyReq, ItemBuyReq.Size );<br />ASSERT_TRUE( bRET );<br />}<br />
  24. 24. class CPacketHandler<br />{<br />CConnectionManager* m_pConnectionManager;<br />CPacketParser* m_pPacketParser;<br />public:<br />CPacketHandler() <br /> {<br />m_pConnectionManager= new CConnectionManager();<br />m_pPacketParser = new CPacketParser();<br /> ...<br />}<br />BOOL ProcessPacket ( const char * pBuf, size_tpacketSize ) <br /> {<br />MSG_BASE* pMsg= m_pPacketParser->ParsePacket( pBuf, packetSize);<br /> ...<br /> if( pMsg->GetProtocol() == MSG_PROTOCOL_ITEM_BUY_REQ ) <br /> {<br />m_pConnectionManager->SendPacket( new PACKET_ITEM_BUY_ANS() );<br /> return TRUE;<br />}<br /> ...<br /> return FALSE;<br />}<br />...<br />};<br />
  25. 25. class CPacketParser<br />{<br />public:<br /> ......<br />MSG_BASE* ParsePacket( const char* pBuf, size_tpacketSize ) <br />{<br /> MSG_BASE* pMsg = (MSG_BASE*)pBuf;<br />... // 검증 코드 및 데이터 채우기<br /> return pMsg;<br />}<br /> ......<br />};<br />
  26. 26. class CConnectionManager<br />{<br />CSendQueue* m_pSendQueue;<br />public:<br /> ......<br />void SendPacket( MSG_BASE* pMsg ) <br /> {<br />// 실제로 메시지를 보내는 코드<br />m_pSendQueue->PostMessage(pMsg);<br />}<br /> ......<br />};<br />
  27. 27. class CConnectionManager<br />{<br />CSendQueue* m_pSendQueue;<br />public:<br /> ......<br />void SendPacket( MSG_BASE* pMsg ) <br /> {<br />// 실제로 메시지를 보내는 코드<br />m_pSendQueue->PostMessage(pMsg);<br />}<br /> ......<br />};<br />
  28. 28.
  29. 29.
  30. 30.
  31. 31. 스텁(Stub)<br />외부 의존물을 대신하기 위해 간접 계층 추가<br />
  32. 32.
  33. 33. 간접 계층<br />외부 의존물에 접근하기 위해 인터페이스 추가<br />
  34. 34.
  35. 35. class CPacketHandler<br />{<br />IConnectionManager* m_pConnectionManager;<br />CPacketParser* m_pPacketParser;<br />public:<br />CPacketHandler() <br /> {<br />m_pConnectionManager= new CConnectionManager();<br />m_pPacketParser = new CPacketParser();<br /> ...<br />}<br />BOOL ProcessPacket ( const char * pBuf, size_tpacketSize ) <br /> {<br /> MSG_BASE* pMsg= m_pPacketParser->ParsePacket( pBuf, packetSize);<br /> ...<br /> if( pMsg->GetProtocol() == MSG_PROTOCOL_ITEM_BUY_REQ ) <br /> {<br />m_pConnectionManager->SendPacket( new PACKET_ITEM_BUY_ANS() );<br /> return TRUE;<br />}<br /> ...<br /> return FALSE;<br />}<br />...<br />};<br />
  36. 36. 스텁 주입하기<br />생성자<br />get, set 프로퍼티<br />매개변수<br />추상 팩토리<br />
  37. 37. 생성자 주입<br />장점<br />테스트 코드의 가독성 향상<br />해당 매개 변수가 필수임을 알림<br />단점<br />상호 참조의 경우 생성 문제<br />매개 변수의 개수가 늘어날 수록 가독성, 관리용이성 악화<br />class CPacketHandler<br />{<br />IConnectionManager* m_pConnectionManager;<br /> ...<br />public:<br />CPacketHandler(IConnectionManager* pManager) <br /> {<br />m_pConnectionManager= pManager;<br /> ...<br />}<br />...<br />};<br />...<br />FakeConnectionManagerFakeManager;<br />CPacketHandlerHandler( &FakeManager );<br />...<br />
  38. 38. class CPacketHandler<br />{<br />IConnectionManager* m_pConnectionManager;<br /> ...<br />public:<br />SetConnectionManager<br /> (IConnectionManager* pManager) <br /> {<br />m_pConnectionManager = pManager;<br />}<br /> ...<br />};<br />...<br />FakeConnectionManagerFakeManager;<br />CPacketHandler Handler;<br />Handler.SetConnectionManager( &FakeManager );<br />...<br />get, set 프로퍼티<br />작성의 용이함<br />필수적이지 않은 매개변수<br />
  39. 39. 그 외 대표적 방법들<br />매개변수 전달<br />함수를 호출할 때 함께 의존물을 넣어준다.<br />추상 팩토리<br />실제 객체와 스텁을 생성하는 팩토리를 생성하는 추상 팩토리를 생성<br />
  40. 40. 캡슐화 문제<br />테스트 용이성을 높이기 위한 방법<br />Public<br />상속<br />Friend<br />조건부 컴파일(#ifdef)<br />상용 프레임워크<br />
  41. 41. 픽스쳐<br />class fixture_name;<br />TEST_F( fixture_name, case_name)<br />{<br />...<br />...// Some Tests<br />ASSERT_XXX();<br />...<br />}<br />
  42. 42. class fixture_name : public testing::Test<br />{<br /> void SetUp();<br />void TearDown();<br />};<br />TEST_F( fixture_name, case_name)<br />{<br />...<br />...// Some Tests<br />ASSERT_XXX();<br />...<br />}<br />
  43. 43. 목 객체(Mock Object)<br />단위 테스트의 통과, 실패를 판단하는 가짜 객체<br />하나의 테스트에 하나의 목 객체 사용<br />
  44. 44. 스텁 vs 목<br />스텁: 객체의 대체제. 테스트가 가능하도록 의존물을 없애는 것<br />목: 테스트의 통과, 실패를 검증<br />
  45. 45. 목 객체의 사용<br />CPacketHandler가 IConnectionManager::SendPacket() 메서드를 호출하는지 확인<br />ConnectionManager의 인터페이스를 추출, 스텁으로 교체.<br />스텁의SendPacket메서드를오버라이드 하여 체크<br />
  46. 46. class FakeConnectionManager: public IConnectionManager{<br />public:<br />intm_nCalled;<br />MSG_BASE* m_pPacket;<br /> ...<br />virtual void SendPacket( MSG_BASE* pPacket ){<br /> ++m_nCalled;<br />m_pPacket = pPacket;<br />}<br />};<br />TEST( PacketHandler, ProcessPacketWithItemBuyReq){<br />...<br />Handler.ProcessPacket( &ItemBuyReq );<br />ASSERT_EQ( 1, FakeManager.m_nCalled );<br />ASSERT_EQ( MSG_PROTOCOL_ITEM_BUY_ANS, FakeManager.m_pPacket->GetProtocol() );<br />}<br />
  47. 47. 격리 프레임워크(Isolation Framework)<br />목과 스텁 객체를 쉽게 생성할 수 있게 해주는 API의 모음<br />테스트의 반복 작성시 도움을 받을 수 있다.<br />예상값(기대값)의 측정<br />함수 호출<br />호출 횟수<br />인자<br />
  48. 48. Google Mock 사용법<br />목 오브젝트 생성<br />class Impl{<br />public:<br />virtual void SetPos(float x, float y);<br />virtual float GetX() const;}<br />class MockImpl: public Impl{<br />public:MOCK_METHOD2( SetPos, void( float x, float y );<br />MOCK_CONST_METHOD0( GetX, float() );};<br />
  49. 49. 함수 호출 측정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br />EXPECT_CALL( impl, GetPos() );<br /> EXPECT_CALL( impl, SetPos( _, _ ) );<br />…<br />// calls function<br />…<br />}<br />
  50. 50. 함수 호출 횟수 측정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br />EXPECT_CALL( impl, GetPos() )<br /> .Times( 3 );<br />…<br />// calls function<br />…<br />}<br />
  51. 51. 리턴값 지정<br />TEST( MockExample, Expect_call )<br />{<br />MockImplimpl;<br /> // ON_CALL( impl, GetPos() )<br />EXPECT_CALL( impl, GetPos() )<br /> .WillByDefault(Return(50.0f));<br />…<br />// calls function<br />…<br />}<br />
  52. 52. Class FakeConnectionManager: public IConnectionManager{<br />public:<br />intm_nCalled;<br />MSG_BASE* m_pPacket;<br /> ...<br />virtual void SendPacket( MSG_BASE* pPacket ){<br /> ++m_nCalled;<br />m_pPacket = pPacket;<br />}<br />};<br />TEST( PacketHandler, ProcessPacketWithItemBuyReq ){<br />FakeConnectionManagerFakeManager;<br />PacketHandler Handler(&FakeManager);<br />...<br />Handler.ProcessPacket( &ItemBuyReq );<br />ASSERT_EQ( 1, FakeManager.m_nCalled );<br />ASSERT_EQ( MSG_PROTOCOL_ITEM_BUY_ANS, FakeManager.m_pPacket->GetProtocol() );<br />}<br />
  53. 53. class FakeConnectionManager: public IConnectionManager{<br />public:<br />MOCK_METHOD1( SendPakcet, void(MSG_BASE* pPacket);<br />};<br />intIsPacket(MSG_BASE *p){<br />return (p != NULL) && (p->GetProtocol() == MSG_PROTOCOL_ITEM_BUY_ANS);<br />}<br />TEST( PacketHandler, ProcessPacketWithItemBuyReq ){<br />FakeConnectionManagerFakeManager;<br />EXPECT_CALL( FakeManager, SendPacket( Truly(IsPacket) ) )<br /> .Times( AtLeast(1) );<br />PacketHandler Handler( &FakeManager );<br />...<br />Handler.ProcessPacket( &ItemBuyReq);<br />}<br />
  54. 54. 팁<br />목 객체는 테스트 당 1개<br />목 객체, 테스트 객체를 제외한 모든 의존물은Stub으로 대체<br />ASSERT는 가급적 테스트 당 1개<br />목 객체를 재사용 : 목 객체 내부에 ASSERT 삽입 금지<br />모든 테스트는 격리해서 실행<br />
  55. 55. 감사합니다<br />whoo24@gmail.com<br />Twitter: whoo24<br />Blog : http://blog.wychoe.net<br />
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×