Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006)[200611] Korean

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Favorites, Groups & Events

    Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006)[200611] Korean - Presentation Transcript

    1. 테스트 주도 개발 : 무엇을 왜 , 어떻게 ? 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. 결론
    2. 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; } }
    3.  
    4. TDD 는 이런 문제점에 초점이 맞춰져 있다 .
      • 몇 분 안에 진행
      TDD 주기 체크인 Check in TEST (ShieldLevelStartsFull) { Shield shield; CHECK_EQUAL (Shield::kMaxLevel, shield.GetLevel()); } Shield::Shield() : m_level (Shield::kMaxLevel) { } 테스트 작성 코드 작성 리펙토링 테스트 실패 테스트 통과 테스트 통과
    5. 좋은 점 : 단순함 , 모듈화
    6. 좋은 점 : 안전망
    7. 좋은 점 : Instant feedback
      • 마일스톤 : ~2 개월
      • 주기 : 2-4 주
      • Nightly 빌드 : 1 일
      • 자동 빌드 : ~1 시간
      • TDD: 3-4 분간에 30 여번
    8.  
    9. 좋은 점 : 문서화
    10. TDD != 단위 테스트 TDD != 테스트 방법 TDD == 개발 방법론
      • 1. TDD 란 ?
      • 2. TDD 쓰는 법
      • 3. TDD 와 게임
      • 4. 배운 점
      • 5. 결론
    11. 캐릭터 + 방패 Character Damage(x) Shield Damage(x) class Character { IShield* m_shield; public: Character(); void Damage(float amount); float GetHealth() const; };
    12. 3 가지 테스트 방법
      • 리턴 값 검사
      • 상태 검사
      • 객체 상호작용 검사
    13. 리턴값 검사 TEST (ShieldCanBeDamagedIfFull) { } Shield Test Shield bool Damage() Damage? Shield shield; CHECK (shield.Damage()); “ Failure in ShieldLevelStartsFull: Expected 100 but got 0”
    14. 상태 검사 TEST (LevelCannotBeDamagedBelowZero) { } Shield Test Shield Damage(200) GetLevel() Shield shield; shield.Damage(200); CHECK_EQUAL (0, shield.GetLevel()); 0?
    15. 어디에 테스트를 둘까 ?
      • TestGame.exe (links with Game.lib)
      • #ifdef UNIT_TESTS
      • GameTests.DLL
      • GameTests.upk
    16. 테스트 작성
      • 테스트를 쉽게 추가하기 위해 단위 테스트 프레임워크를 사용
      • UnitTest++ 는 게임에 잘 맞아떨어짐 .
    17. 매 빌드마다 테스트 돌리기
    18. 테스트 상호작용 ( 문제가 될 수 있는 부분 ) Test Character Character Damage() *m_shield TEST(CharacterUsesShieldToAbsorbDamage) { Character character(400); character.Damage(100); CHECK_EQUAL(390, character.GetHealth()); } 390? Shield GetHealth() Fancy Shield
    19. 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
    20. 테스트에 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?
    21. 실천법 : 가까이 있는 코드만 테스트하기 Test Code under test Test Code under test Subsystem A Subsystem B Subsystem C Something the cat dragged in The kitchen sink Who knows
    22. Best Practices: Keep Tests Simple TEST (ShieldStartsAtInitialLevel) { ShieldComponent shield(100); CHECK_EQUAL (100, shield.GetLevel()); } TEST (ShieldTakesDamage) { ShieldComponent shield(100); shield.Damage(30); CHECK_EQUAL (70, shield.GetLevel()); } TEST (LevelCannotDropBelowZero) { ShieldComponent shield(100); shield.Damage(200); CHECK_EQUAL (0, shield.GetLevel()); } TEST(ActorDoesntMoveIfPelvisBodyIsInSamePositionAsPelvisAnim) { component = ConstructObject<UAmpPhysicallyDrivableSkeletalComponent>(); component->physicalPelvisHandle = NULL; component->SetOwner(owner); component->SkeletalMesh = skelMesh; component->Animations = CreateReadable2BoneAnimSequenceForAmpRagdollGetup(component, skelMesh, 10.0f, 0.0f); component->PhysicsAsset = physicsAsset; component->SpaceBases.AddZeroed(2); component->InitComponentRBPhys(false); component->LocalToWorld = FMatrix::Identity; const FVector actorPos(100,200,300); const FVector pelvisBodyPositionWS(100,200,380); const FTranslationMatrix actorToWorld(actorPos); owner->Location = actorPos; component->ConditionalUpdateTransform(actorToWorld); INT pelvisIndex = physicsAsset->CreateNewBody(TEXT(&quot;Bone1&quot;)); URB_BodySetup* pelvisSetup = physicsAsset->BodySetup(pelvisIndex); FPhysAssetCreateParams params = GetGenericCreateParamsForAmpRagdollGetup(); physicsAsset->CreateCollisionFromBone( pelvisSetup, skelMesh, 1, params, boneThings); URB_BodyInstance* pelvisBody = component->PhysicsAssetInstance->Bodies(0); NxActor* pelvisNxActor = pelvisBody->GetNxActor(); SetRigidBodyPositionWSForAmpRagdollGetup(*pelvisNxActor, pelvisBodyPositionWS); component->UpdateSkelPose(0.016f); component->RetransformActorToMatchCurrrentRoot(TransformManipulator()); const float kTolerance(0.002f); FMatrix expectedActorMatrix; expectedActorMatrix.SetIdentity(); expectedActorMatrix.M[3][0] = actorPos.X; expectedActorMatrix.M[3][1] = actorPos.Y; expectedActorMatrix.M[3][2] = actorPos.Z; const FMatrix actorMatrix = owner->LocalToWorld(); CHECK_ARRAY2D_CLOSE(expectedActorMatrix.M, actorMatrix.M, 4, 4, kTolerance); }
    23. 실천법 : 테스트를 빠르게 유지하기 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.
    24. 실천법 : 테스트를 빠르게 유지하기 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.
    25. 실천법 : 테스트를 독립적으로 유지하기 g_CollisionWorldSingleton
      • 1. TDD 란 ?
      • 2. TDD 쓰는 법
      • 3. TDD 와 게임
      • 4. 배운 점
      • 5. 결론
    26. 콘솔에서는 테스트를 덜 자주 돌렸습니다 .
    27.  
    28. 전체 API 를 wrap 하기
    29. API 상태를 직접 테스트하기
    30. API 함수 호출 뺀 나머지 코드를 테스트하기
    31. 미들웨어를 끼고 테스트하기 Havok RenderWare Unreal Novodex OpenGL DirectX
    32. 만들어진 엔진을 끼고 TDD 하기
    33. TDD 를 해 보고 싶지만 ...
      • 1. TDD 란 ?
      • 2. TDD 사용법
      • 3. TDD 와 게임
      • 4. 배운 점
      • 5. 결론
    34. 교훈 #1: TDD 는 고수준 게임 코드에도 사용될 수 있다 .
    35. 공격형 인공지능 예 function TestEnemyChoosesLightAttack() { FightingComp = new(self) class'FightingComponent'; FightingComp.AddAttack(LightAttack); FightingComp.AddAttack(HeavyAttack); enemy.AttachComponent(FightingComp); enemy.FightingComponent = FightingComp; enemy.FindPlayerPawn = MockFindPlayerPawn; enemy.ShouldMeleeAttack = MockShouldAttack; ShouldMeleeAttackReturn = true; enemy.Tick(0.666); CheckObjectsEqual(LightAttack, FightingComp.GetCurrentAttack()); }
    36. 캐릭터 행동의 예 TEST_F( CharacterFixture, SupportedWhenLeapAnimationEndsTransitionsRunning ) { LandingState state(CharacterStateParameters(&character), AnimationIndex::LeapLanding); state.Enter(input); input.deltaTime = character.GetAnimationDuration( AnimationIndex::LeapLanding ) + kEpsilon; character.supported = true; CharacterStateOutput output = state.Update( input ); CHECK_EQUAL(std::string(&quot;TransitionState&quot;), output.nextState->GetClassInfo().GetName()); const TransitionState& transition = *output.nextState; CHECK_EQUAL(std::string(&quot;RunningState&quot;), transition.endState->GetClassInfo().GetName()); }
    37. 구조의 선택
    38. 교훈 #2: TDD 와 코드 디자인
    39. 교훈 #3: 테스트 개수로 작업 진행 상황 알기
    40. 교훈 #4: 빌드 안정성을 높여주는 TDD
    41. 교훈 #5: TDD 는 더 많은 코드를 만들어 낸다 .
    42. 교훈 #6: 개발 속도
    43. 교훈 #7: TDD 도입하기
    44. 교훈 #7: TDD 도입하기
      • High risk – High reward
    45. 1. TDD 란 ? 2. TDD 쓰는 법 3. TDD 와 게임 4. 배운 점 5. 결론
    46. 결론
    47. 질문 ?
      • Resources
      • Games from Within http://www.gamesfromwithin.com
      • Includes paper for this presentation with more details and links to other TDD resources and the UnitTest++ framework.
      Noel Llopis - [email_address]

    + Ryan ParkRyan Park, 3 years ago

    custom

    1402 views, 0 favs, 2 embeds more stats

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 1402
      • 1185 on SlideShare
      • 217 from embeds
    • Comments 0
    • Favorites 0
    • Downloads 71
    Most viewed embeds
    • 214 views on http://kaistizen.net
    • 3 views on http://rubis.tistory.com

    more

    All embeds
    • 214 views on http://kaistizen.net
    • 3 views on http://rubis.tistory.com

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories