Test Driven Game Development
Test Driven Development (TDD) has steadily grown in popularity among non-game programmers. Despite this, it has not been widely adopted in game development. Today I’m going to discuss why TDD is suited to games development and how it frees developers and designers to experiment with “finding the fun” without breaking core gampelay.
Example – Mario
Let’s begin with an example. You’re writing Super Mario Brothers and want to experiment with how Mario jumps. You can change the jumping however you like, but he needs to always jump at least 20 pixels. Your unit test might look something like this:
[Test]
void Mario_Can_Jump_20_Pixel_Gap()
{
Mario mario = new Mario();
mario.Position = new Vector2(0,0);
mario.Jump(Right);
mario.Update(10);
Assert.IsTrue(mario.Position.X >= 20); // Has moved at least 20 pixels
Assert.IsTrue(mario.Position.Y == 0); // Is on the ground
}
You are now free to make any update you want to Jump() knowing that if the test passes, your requirements of jump at least 20 pixels is met. This is much easier than loading up a level, trying the jump and making sure it all works.
Advantages
So why would you want to use Test Driven Game Development?
- Guarantee code works. With a full suite of unit tests you are guaranteed that your code does what it is supposed to do. Bugs will be found as soon as they are introduced as tests fail immediately.
- Forces modular code. Notice there was no mention of UI, controllers or rendering in the example unit test. This “Separation of Concerns” is not only good design, it’s also required if want to have testable code.
- Allows you to “find the fun”. Once you’re guaranteed that certain requirements are met, you’re free to experiment with gameplay to make it more enjoyable without breaking certain levels or unbalancing the game. This also extends to giving designers more freedom when scripting. Encouraging experimentation by designers without programmer intervention is invaluable.
Good and Bad
Some parts of game development are perfectly suited to TDD while others may cause more trouble than good. Firstly the areas that would greatly benefit from TDD:
- Game Engine. Have a list of features/API exposed that is perfect for unit testing. Unit tests serve as code documentation with code samples of usage. It helps reduce the changes of introducing breaking changes to new build of the engine. Performance tests can also be included.
- Core Gameplay. Designers write up tests for core gameplay and formalize game design into testable units. Again, this frees designers and programmers to experiment without breaking core gameplay.
The main area that TDD doesn’t fit is in UI and rendering:
- User Interface/Rendering. Even outside the games industry, UI is difficult to test with unit tests. This is particularly true for 3D UI’s. This issue can be overcome with a good separation of concerns. Keep UI and rendering separate from game logic so testability is still high. One solution is using the MVC pattern for your game engine. I will discuss this further in a future blog post.
Basic Tips
Below are some basic tips that will help get you started with TDD if you haven’t used it before.
- Keep tests short – test only one thing in each unit test
- Keep tests fast – run entire test suite in seconds
- Keep tests thorough – use code coverage to determine what is and isn’t tested, making sure all critical code is tested.
Conclusion
I’ve touched briefly on why Test Driven Development works well with game development and I encourage you to read further into TDD if you have not used it before. As usual, I’d recommend picking a small project and experiment with TDD. Perseverance is key as it may seem as though things are slowing down, but as a project grows and evolves your efforts will be rewarded.
If you’re currently using TDD for your game I’d be interested in hearing your story.
For the definitive book on Test Driven Development, check out: