Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006)[200611] Korean - Presentation Transcript
테스트 주도 개발 : 무엇을 왜 , 어떻게 ? Noel Llopis Senior Architect High Moon Studios 번역 : 박일 http://ParkPD.egloos.com [email_address]
1. TDD 란 ?
2. TDD 쓰는 법 ?
3. TDD 와 게임
4. 배운 점
5. 결론
1. TDD 란 ?
( 왜 이걸 쓰고 싶어할까 ? )
2. TDD 쓰는 법
3. TDD 와 게임
4. 배운 점
5. 결론
define G(n) int n(int t, int q, int d) #define X(p,t,s) (p>=t&&p<(t+s)&&(p-(t)&1023)<(s&1023)) #define U(m) *((signed char *)(m)) #define F if(!--q){ #define I(s) (int)main-(int)s #define P(s,c,k) for(h=0; h>>14==0; h+=129)Y(16*c+h/1024+Y(V+36))&128>>(h&7)?U(s+(h&15367))=k:k G (B) { Z; F D = E (Y (V), C = E (Y (V), Y (t + 4) + 3, 4, 0), 2, 0); Y (t + 12) = Y (t + 20) = i; Y (t + 24) = 1; Y (t + 28) = t; Y (t + 16) = 442890; Y (t + 28) = d = E (Y (V), s = D * 8 + 1664, 1, 0); for (p = 0; j < s; j++, p++) U (d + j) = i == D | j < p ? p--, 0 : (n = U (C + 512 + i++)) < ' ' ? p |= n * 56 - 497, 0 : n; } n = Y (Y (t + 4)) & 1; F U (Y (t + 28) + 1536) |= 62 & -n; M U (d + D) = X (D, Y (t + 12) + 26628, 412162) ? X (D, Y (t + 12) + 27653, 410112) ? 31 : 0 : U (d + D); for (; j < 12800; j += 8) P (d + 27653 + Y (t + 12) + ' ' * (j & ~511) + j % 512, U (Y (t + 28) + j / 8 + 64 * Y (t + 20)), 0); } F if (n) { D = Y (t + 28); if (d - 10) U (++Y (t + 24) + D + 1535) = d; else { for (i = D; i < D + 1600; i++) U (i) = U (i + 64); Y (t + 24) = 1; E (Y (V), i - 127, 3, 0); } } else Y (t + 20) += ((d >> 4) ^ (d >> 5)) - 3; } }
TDD 는 이런 문제점에 초점이 맞춰져 있다 .
몇 분 안에 진행
TDD 주기 체크인 Check in TEST (ShieldLevelStartsFull) { Shield shield; CHECK_EQUAL (Shield::kMaxLevel, shield.GetLevel()); } Shield::Shield() : m_level (Shield::kMaxLevel) { } 테스트 작성 코드 작성 리펙토링 테스트 실패 테스트 통과 테스트 통과
좋은 점 : 단순함 , 모듈화
좋은 점 : 안전망
좋은 점 : Instant feedback
마일스톤 : ~2 개월
주기 : 2-4 주
Nightly 빌드 : 1 일
자동 빌드 : ~1 시간
TDD: 3-4 분간에 30 여번
좋은 점 : 문서화
TDD != 단위 테스트 TDD != 테스트 방법 TDD == 개발 방법론
1. TDD 란 ?
2. TDD 쓰는 법
3. TDD 와 게임
4. 배운 점
5. 결론
캐릭터 + 방패 Character Damage(x) Shield Damage(x) class Character { IShield* m_shield; public: Character(); void Damage(float amount); float GetHealth() const; };
3 가지 테스트 방법
리턴 값 검사
상태 검사
객체 상호작용 검사
리턴값 검사 TEST (ShieldCanBeDamagedIfFull) { } Shield Test Shield bool Damage() Damage? Shield shield; CHECK (shield.Damage()); “ Failure in ShieldLevelStartsFull: Expected 100 but got 0”
상태 검사 TEST (LevelCannotBeDamagedBelowZero) { } Shield Test Shield Damage(200) GetLevel() Shield shield; shield.Damage(200); CHECK_EQUAL (0, shield.GetLevel()); 0?
어디에 테스트를 둘까 ?
TestGame.exe (links with Game.lib)
#ifdef UNIT_TESTS
GameTests.DLL
GameTests.upk
테스트 작성
테스트를 쉽게 추가하기 위해 단위 테스트 프레임워크를 사용
UnitTest++ 는 게임에 잘 맞아떨어짐 .
매 빌드마다 테스트 돌리기
테스트 상호작용 ( 문제가 될 수 있는 부분 ) Test Character Character Damage() *m_shield TEST(CharacterUsesShieldToAbsorbDamage) { Character character(400); character.Damage(100); CHECK_EQUAL(390, character.GetHealth()); } 390? Shield GetHealth() Fancy Shield
class IShield { public: virtual float Damage(float amount) = 0; } class FancyShield : public IShield { public: float Damage(float amount) { … }; } class MockShield : public IShield { public: float damagePassedIn; float damageToReturn; float Damage(float amount) { damagePassedIn = amount; return damageToReturn; } } A mock object stands in for an object outside the unit you're testing
테스트에 Mock 쓰기 Test Character TEST(CharacterUsesShieldToAbsorbDamage) { } MockShield MockShield mockShield = new MockShield; mockShield->damageToReturn = 10; Character character(400, mockShield); character.Damage(200); CHECK_EQUAL(200, mockShield->damagePassedIn); CHECK_EQUAL(390, character.GetHealth()); Character Damage() *m_shield Parameters correct? GetHealth() Returned damage correctly used?
실천법 : 가까이 있는 코드만 테스트하기 Test Code under test Test Code under test Subsystem A Subsystem B Subsystem C Something the cat dragged in The kitchen sink Who knows
실천법 : 테스트를 빠르게 유지하기 Slow Test(24 > 20 ms): CheckSpotOverlapIsHandledCorrectly1Test Slow Test(25 > 20 ms): CheckSpotOverlapIsHandledCorrectly2Test Slow Test(24 > 20 ms): DeleteWaveEventFailsIfEventDoesntExistInCueTest Slow Test(22 > 20 ms): CanGetObjectsInBrowserListPackageTest Slow Test(48 > 20 ms): HmAddActorCallsCreateActorTest Slow Test(74 > 20 ms): HmReplaceActorDoesNothingIfEmptySelectionTest Slow Test(57 > 20 ms): HmReplaceActorWorksIfTwoActorsSelectedTest Slow Test(26 > 20 ms): ThrowExceptionWhenTrackIndexOutOfRangeTest Total time spent in 1923 tests: 4.83 seconds. Time spent in 26 slow tests: 2.54 seconds.
실천법 : 테스트를 빠르게 유지하기 Running unit tests TestDebugServer in Debug... 116 tests run There were no test failures. Test time: 0.016 seconds. Running unit tests for TestStreams in Debug... 138 tests run There were no test failures. Test time: 0.015 seconds. Running unit tests TestMath in Debug... 245 tests run There were no test failures. Test time: 0.001 seconds. Running unit tests... 184 tests run There were no test failures. Test time: 0.359 seconds.
실천법 : 테스트를 독립적으로 유지하기 g_CollisionWorldSingleton
1. TDD 란 ?
2. TDD 쓰는 법
3. TDD 와 게임
4. 배운 점
5. 결론
콘솔에서는 테스트를 덜 자주 돌렸습니다 .
전체 API 를 wrap 하기
API 상태를 직접 테스트하기
API 함수 호출 뺀 나머지 코드를 테스트하기
미들웨어를 끼고 테스트하기 Havok RenderWare Unreal Novodex OpenGL DirectX
0 comments
Post a comment