생산적인 개발을 위한 지속적인 테스트
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

생산적인 개발을 위한 지속적인 테스트

on

  • 2,905 views

 

Statistics

Views

Total Views
2,905
Views on SlideShare
1,985
Embed Views
920

Actions

Likes
0
Downloads
28
Comments
0

9 Embeds 920

http://mypage.sarang.net 565
http://devnote.tistory.com 273
http://birdkr.tistory.com 29
http://www.euiweonjeong.com 24
http://www.hanrss.com 20
http://www.slideshare.net 3
http://twitter.com 3
http://euiweon.synology.me 2
http://euiweonjeong.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

생산적인 개발을 위한 지속적인 테스트 Presentation Transcript

  • 1. (birdkr@gmail.com) birdkr@gmail.com)
  • 2. ?
  • 3. CruiseControl.NET
  • 4. CruiseControl.NET
  • 5. CruiseControl.NET • • Asset • • • • • (doxygen) •
  • 6. ?
  • 7. 1. . 2. . 3. , .
  • 8. 테스트 결과 로그 <?xml version="1.0"?> <maiettest-results tests=“2" failedtests=“1" failures="1" time="0.137"> <report text="time : 680 sec" /> <report text=“총 클라이언트 개수 : 4650" /> <test name=“로그인 반복" time="0.062" > <success message="success" /> </test> <test name=“캐릭터 생성 반복" time="0.062" > <failure message="Crash!" /> </test> </maiettest-results>
  • 9. 테스트 결과 로그 • 테스트 결과를 XML로 만들고, XSL을 이용 하여 CruseControl.NET에 출력한다.
  • 10. Feedback
  • 11. Unit Test • • .
  • 12. Unit Test TEST(TestMathFunctionTruncateToInt) { CHECK_EQUAL(0, GMath::TruncateToInt(0.0)); CHECK_EQUAL(5, GMath::TruncateToInt(5.6)); CHECK_EQUAL(13, GMath::TruncateToInt(13.2)); CHECK_EQUAL(13, GMath::TruncateToInt(13.2)); CHECK_EQUAL(-6, GMath::TruncateToInt(-5.6)); CHECK_EQUAL(-3, GMath::TruncateToInt(-2.1)); }
  • 13. Unit Test TEST(ShieldCanBeDamaged) { World world; world.Create(); Player player; player.Create(world, vec3(1000,1000,0)); player.SetHealth(1000); Shield shield; shield.SetHealth(100); player.Equip(shield); player.Damage(200); CHECK(shield.GetHealth() == 0); CHECK(player.GetHealth() == 900); }
  • 14. Unit Test
  • 15. Unit Test TEST_FIXTURE(FLogin, TestLogin_MC_COMM_REQUEST_LOGIN_SERVER_Success) { MakeParam_TD_LOGIN_INFO(); TD_LOGIN_INFO tdLoginInfo = MakeParam_TD_LOGIN_INFO(); OnRecv_MMC_COMM_REQUEST_LOGIN_SERVER(m_nRequestID, m_nConnectionKey, &tdLoginInfo tdLoginInfo); OnRecv_MMC_COMM_REQUEST_LOGIN_SERVER(m_nRequestID, m_nConnectionKey, &tdLoginInfo); // 로그인 하기 전의 값 체크 CHECK_EQUAL(0, gmgr.pPlayerObjectManager->GetPlayersCount()); // 클라이언트로부터 존 입장 패킷 받음 OnRecv_MC_COMM_REQUEST_LOGIN_SERVER(m_nConnectionKey); OnRecv_MC_COMM_REQUEST_LOGIN_SERVER(m_nConnectionKey); // 마스터 서버로 인증키 확인 패킷 보냈는지 체크 CHECK_EQUAL(MC_COMM_RESPONSE_LOGIN_SERVER, m_pLink- GetCommandID(0)); CHECK_EQUAL(MC_COMM_RESPONSE_LOGIN_SERVER, m_pLink->GetCommandID(0)); CHECK_EQUAL(RESULT_SUCCESS, m_pLink- GetParam<int>(0, CHECK_EQUAL(RESULT_SUCCESS, m_pLink->GetParam<int>(0, 0)); CHECK_EQUAL(m_pLink->GetUID(), m_pLink->GetParam<MUID>(0, 1)); CHECK_EQUAL(m_pLink- GetUID(), m_pLink- GetParam<MUID>(0, // 로그인 후 값 체크 CHECK_EQUAL(1, gmgr.pPlayerObjectManager->GetPlayersCount()); GPlayerObject* pPlayerObject = gmgr.pPlayerObjectManager->GetPlayer(m_pLink->GetUID()); CHECK(pPlayerObject != NULL); CHECK_EQUAL(m_nGUID, pPlayerObject->GetAccountInfo().nGUID); CHECK_EQUAL(string(“birdkr”), string(pPlayerObject->GetAccountInfo().strID)); }
  • 16. Mock Object class MockPlayer : public GPlayer { public: MockPlayer() {}; virtual ~ MockPlayer() {}; … virtual void SendToThisSector (MPacket* pPacket) override { } virtual void SendToMe(MPacket * pPacket) override { } virtual void SendToGuild(MPacket* pPacket) override { } … };
  • 17. , class XSystem { public: virtual unsigned int GetNowTime() { return timeGetTime() timeGetTime()(); } virtual int RandomNumber(int nMin, int nMax) { return (rand() % (nMax - nMin + 1)) + nMin; rand() rand } };
  • 18. , class MockSystem : public XSystem { protected: unsigned int m_nExpectedNowTime; public: virtual unsigned int GetNowTime() { if (m_nExpectedNowTime != 0) return m_nExpectedNowTime; return XSystem::GetNowTime(); } void ExpectNowTime(unsigned int nNowTime) { m_nExpectedNowTime = nNowTime; } };
  • 19. , TEST_FIXTURE(FPlayerInOut2, TestObjectCacheDelete) { vec3 vNewPos = vec3(100.0f, 100.0f, 0.0f); CHECK_EQUAL(2, gg.omgr->GetCount()); m_pNet->OnRecv( MC_ENTITY_WARP, 3, NEW_ID(m_pMyPlayer->GetID Update(0.1f); CHECK_CLOSE(100.0f, m_pMyPlayer->GetPosition().x, 0.001f); CHECK_CLOSE(100.0f, m_pMyPlayer->GetPosition().y, 0.001f); XExpectNowTime(XGetNowTime() + 10000 ); Update(10.0f); // 멀리 있는 다른 플레이어가 지워졌다. CHECK_EQUAL(1, gg.omgr->GetCount()); }
  • 20. , template <class Type> class GTestMgrWrapper : public MInstanceChanger<Type> { public: GTestMgrWrapper() : MInstanceChanger() { m_pOriginal = gmgr.Change(m_pTester); } ~GTestMgrWrapper() { gmgr.Change(m_pOriginal); } };
  • 21. , TEST_FIXTURE(FChangeMode, TestNPC_SightRange) { GTestMgrWrapper<GNPCInfoMgr> m_NPCInfoMgrWrapper; m_NPCInfo.nSightRange = 1000; GNPC* pNPC = m_pMap->SpawnTestNPC(&m_NPCInfo); CHECK_EQUAL(1000, pNPC->GetSightRange()); pNPC->ChangeMode(NPC_MODE_1); CHECK_EQUAL(500, pNPC->GetSightRange()); }
  • 22. Refactoring Test Code • Mock Object • override • Google C++ Mocking Framework!
  • 23. Refactoring Test Code • UnitTestHelper – Helper . – ) GUTHelper_NPC::SpawnNPC()
  • 24. Refactoring Test Code • Fixture . class FBasePlayer; class FBaseItem; class FBaseNPC; class FBaseMap; class FBaseNetClient;
  • 25. Refactoring Test Code • Fixture . class FForCombatTest : public FBaseMockLink, public FBaseNetClient, public FBasePlayer, public FBaseMap, public FBaseMapMgr, public FBasePlayer { … };
  • 26. Refactoring Test Code Class Fduel // Fixture { … void CHECK_DuelCancel() { CHECK_EQUAL(m_pLinkRequester->GetCommand(0).GetID(), MC_DUEL_CANCEL); CHECK_EQUAL(m_pLinkTarget->GetCommand(0).GetID(), MC_DUEL_CANCEL); } void CHECK_DuelFinished(CPlayer* pWinner, CPlayer* pLoser) { MockLink* pWinnerLink = (pWinner==m_pPlayerRequester) ? M_pLinkRequester : m_pLinkT const Mcommand& Command = pWinnerLink->GetCommand(); CHECK_EQUAL(Command.GetID(), MC_DUEL_FINISHED); int nWinnerID, nLoserID; Command.GetParam(&nWinnerID, 0, MPT_INT); Command.GetParam(&nLoserID, 0, MPT_INT); CHECK_EQUAL(nWinnerID, pWinner->GetID()); CHECK_EQUAL(nLoserID, pLoser->GetID()); } }
  • 27. Refactoring Test Code TEST_FIXTURE(FDuel, DuelQuestionRefuse) { CHECK_EQUAL(gmgr.pDuelMgr->GetCount(), 0); DuelRequest(); CHECK_EQUAL(gmgr.pDuelMgr->GetCount(), 1); BeginCommandRecord(); DuelResponse(false); CHECK_DuelCancel(); }
  • 28. Database Unit Test • 저장 프로시저, 트리거 등에 대한 유닛 테스 트 • xDBUnit 프레임워크가 있지만 자체적으로 작성했다. – UnitTest++ 사용
  • 29. Database Unit Test • 테스트 단계 1. SandBox에 데이터베이스, Table, SP 등 생성 2. 테스트에 필요한 데이터 집합(Seed Dataset) 을 생성 3. 테스트 케이스 실행 4. 데이터 변경 검증
  • 30. Seed DataSet
  • 31. Unit Test Code DBTEST(FGuildDB, CreateGuild) { UTestDB.Seed(“GuildTestSeedData.xml”); uint32 nMasterCID = DBTestHelper::GetCID(“Acc5Char1”); uint32 nMem1 = DBTestHelper::GetCID(“Acc5Char2”); uint32 nMem2 = DBTestHelper::GetCID(“Acc5Char3”); CHECK((0 != nMasterCID) && (0 != nMem1) && (0 != nMem2)); // 길드 생성 TDBRecordSet rs1; UTestDB.Execute(rs1, “{CALL spGuildCreate (‘%S’, %d)}”, “TGuild4”, nMasterCID); int nGID = rs1.Field(“GID”).AsInt(); CHECK(0 != nGID); // 길드가 추가되었는지 레코드 개수 확인 TDBRecordSet rs2; UTestDB.Execute(rs2, “SELECT COUNT(*) AS cnt FROM dbo.Guild;”); CHECK_EQUAL(1, rs2.GetFetchedCount()); CHECK_EQUAL(1, rs2.Field(“cnt”).AsInt()); }
  • 32. • 특정 씬을 렌더링하여 원본 이미지와 같은 이미지인지 픽셀별로 비교하여 같은 픽셀 값인지 테스트 • 렌더링에 대한 UnitTest를 만들지 못하여 나온 대안 • 랜덤 요소 제거 등의 추가 작업이 필요함
  • 33. • • • • •
  • 34. Recv Replay Send Packet Queue Command Queue Packet Local Local Event 복사 Replay Queue 커맨드 구조 ID Data
  • 35. Resource Validator • 기획자나 아티스트가 작업한 게임 데이터 (Assets)에 논리적으로 잘못된 값이 입력되 었는지 검증 • 예시 – 상점 인터랙션이 설정된 NPC는 비전투형인가? – 아이템 판매 가격이 구매 가격보다 높은가? – 몬스터에 설정된 스킬 애니메이션 파일이 존재하는가? – 맵의 포탈에 연결된 맵이 실재로 존재하는가?
  • 36. Resource Validator • XML Schema • •
  • 37. Resource Validator
  • 38. Runtime Validator • • – DB – – AI – Assertion
  • 39. Runtime Validator
  • 40. • XML . – • , , , – • • Crash
  • 41. AI • • – Crash –
  • 42. Crash Dump Reporter
  • 43. Crash Dump Analyzer • • •
  • 44. Crash Dump Analyzer • • • WinDbg Command-Line •
  • 45. Crash Dump Analyzer
  • 46. Crash Dump Analyzer
  • 47. ?
  • 48. 1. 2. 3.
  • 49. Q/A birdkr@gmail.com http://mypage.sarang.net