8

I'm coding a game in my spare time, but I am mostly still a beginner when it comes to programming. I'm sorry if this question is off topic or if it ends up not being helpful to anyone else, but hopefully it will be.

I've spent a lot of time reading books about the design of code, as well as different methodologies and approaches to coding. In the course of this research I keep running into the concept of Test Driven Development. The people who espouse this idea usually seem very passionate about it. I do believe that it can help the speed and efficiency of writing software. Time is a very precious resource so I would rather learn to do things the best way rather than muddle through without trying to expand my knowledge of the programming craft.

Anyway, possibly because I am a beginner, I cannot imagine how to apply test driven development to games. I've found a couple of articles on the subject but they were not very helpful. Most of the examples of unit tests that I have seen are very simple boilerplate examples, or examples from software that is not at all like a game.

In my own coding, I try to approach it with a similar mindset to test driven development, although I'm sure it does not actually qualify as TDD. I write the minimum amount of code to try to implement whatever feature I am adding to the game, and then I immediately test the game to see if it works. If things don't happen as I intended, I immediately make changes to get it closer to what I want. If it is not working or broken, and if I cannot find the bugs by reading the code, I step through the methods in the debugger until I find the unexpected behavior, and then I remove it. What I am trying to say is that I am constantly testing the game, pretty much after each and every incremental change. Testing drives my development. The "unit test" is in my head, because for example I know what the unit in my game is supposed to be doing, so I test to make sure that it is doing it, and if not, I try to fix it right away.

On to my actual question. How can one write unit tests for a complex game? By complex, I mean with many emergent aspects of gameplay, such that the meat of the gameplay emerges from the interaction between the many different elements inside the game combined with the player's choices. For example, a roguelike rpg with a procedural world. What kind of unit tests would one write for a game like that? How could one apply test driven development to such a game?

bazola
  • 255
  • 1
  • 5

2 Answers2

12

Unit tests don't test gameplay. There's no programmatic criteria to see if a game is fun, or a level is the right difficulty. Unit tests will test that your roguelike mapgen actually produces a level with a stairs up and a stairs down. It will test that your encumberance rules are setup that your character actually moves slower when weighted. It will make sure your character can't wear 50 hats. It will make sure that the mechanics are all implemented correctly in relative isolation.

Telastyn
  • 110,259
2

It is hard to write unit tests for code that is non-deterministic. If you have code involving random numbers, you won't be able to write a unit test that asserts an expected result.

So, unit tests are more appropriate for the code that is deterministic. When I give a method these inputs, I expect these outputs. As an example: when a fighter with 15 strength uses his two-handed broadsword to successfully hit an undead ghoul with 10 armor, I expect 8 damage. The non-deterministic part (whether the hit was successful or not) can't necessarily be unit tested, but what happens after that can be. Even if the amount of damage is expected to be within some range, you can test for that.

If you're having a hard time finding code to write unit tests for, you need to refactor so that the deterministic logic is isolated in methods or classes. Roll the dice to first to determine success, then pass the relevant inputs (class, strength, armor, etc.) to a testable method.

To your comment about having the unit test in your head, the point of unit testing isn't just about freshly written code. It's also about having confidence that the code still works after making inevitable changes.