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