Is unit testing viable in game programming?

Unit Testing

Unit Testing Problem Overview


I'm fond of the idea of unit testing but I'm having trouble applying it to game programming. Games are highly stateful and often the code doesn't break itself into distinct units. In my experience, most functions mutate state rather than returning values.

Consider a simple action like playerJump(height). I'd love to have a test suite that checks a large variety of cases to make sure that jumping always works as expected. However this function will likely return no value and have the side effect of, player.velocity.y = -height and checkCollisions(player). I can't think of a clear unit test to build around this.

Is unit testing just not viable in highly stateful applications like games? Are the advantages of unit testing so great that it would be worth programming games functionally?


Update:

Games from Within has a series of in depth articles about using Test Driven Development in games. I highly recommend them to anybody interested in this subject. Here is the first article:

http://gamesfromwithin.com/stepping-through-the-looking-glass-test-driven-game-development-part-1

Unit Testing Solutions


Solution 1 - Unit Testing

Often the code doesn't break itself into distinct units.

That's just poor design. The code doesn't break itself into anything. You, the designer, have to impose a structure on the code so that you can demonstrate that it actually works.

However, this function will likely return no value...

So?

...and have the side effect of, player.velocity.y = -height and checkCollisions(player).

Then test for that.

I can't think of a clear unit test to build around this.

Why not? You just gave an excellent specification for the results of the function.

You might need a few mock objects to replace the full-blown Player with a simplified MockPlayer that's easier to test with.

But your specification of behavior was perfect. Just test for the things you described.

Solution 2 - Unit Testing

Unit tests can be useful for a lot of the low level libraries you may use with game code but I seriously doubt it is of much use for the higher level stuff. Games are usually simulations and rely on massive amounts of shared state which can't meaningfully be mocked up and tested in isolation. Often functions in games do not return any sort of value that you can instantly check but instead set a process in motion which should complete at some point in the future. Testing such behaviour is worthwhile but requires a significantly different approach to the unit test idea of testing pieces of code in isolation.

Solution 3 - Unit Testing

Programming is programming. Unit tests are useful for any kind of application because they help you detect and correct errors (and often more importantly, regressions inadvertently introduced as you refactor code) immediately and efficiently.

There are of course areas of high level behaviour that are difficult to unit test, but that's not really what unit tests are for - they are primarily for checking that individual methods or small parts of the codebase do what they are supposed to do.

For the higher level behaviours, you need to apply other testing approaches (regression testing, for example: feeding a fixed sequence of inputs into the game and then checking that you get the same results every time, or generating camera views at fixed locations throughout a level and checking that they always generate the same (or at least a reasonably similar) image)

Your example of PlayerJump is one such case. You can unit or regression test this by isolating it with constant inputs (programatically place the player character at a fixed location in a simple test scene and fire the jump event, then check that his collisions or final resting place is consistent. By building up a library of different objects the player can jump "at", you can cover a lot of test cases (e.g. that the jump succeeds over a gap of the prescribed maximum-jump distance).

Beyond that, though, games do require a lot of gameplay testing (where real users simply play it). This will find odd cases that you didn't cover with automated tests, but more importantly it will answer a question that automated testing will never answer: Does it "feel" right? Is it "fun"? These are tests only a human can conduct.

Solution 4 - Unit Testing

My experience with unit and automates testing during the development of Crysis 2 is available here: http://yetanothergameprogrammingblog.blogspot.com/2010/06/aaa-automated-testing.html Hope it helps.

Summary:

Automated testing improved deliverables stability, increasing productivity for both content creators' and engineers Automated testing is an effective tool to improve code quality and reduce the chances of having to work overtime The Game Industry as a whole is very reactionary in general, automated testing meets several irrational arguments against Don't call it testing, call it something else, almost anything else (Look at Behavior-Driven-Development) Be flexible, writing good tests is hard and require skills that are not widely available in the Game Industry

Solution 5 - Unit Testing

Many game programmers use the Entity-component-system architecture. They do it because it makes it easier to modify the behavior to game objects. But as it happens, it also makes it easier to unit test your code.

Solution 6 - Unit Testing

Take a look at PEX for automated unit test generation. It will generate unit tests for all possible input variations, which will help you test a lot of possible combinations.

Solution 7 - Unit Testing

Unit testing just doesn't care at all how "stateful" your unit is. You have a more or less self-contained piece of code, and if its input and output vector are huge then testing is difficult. Whether or not these vectors are laid down as states before and after execution doesn't change a bit about the testing. If you want to tell us however that you can't think of a proper way to define test cases like in most simple-minded unit testing tutorials/papers, i.e. the test subject is something like "f(x) = y" , then yes, I agree, you will have a hard time proving that the few (x[100],y[99]) vectors that a human cane come up with yield sufficient coverage (numerics!). Try to formulate integrative properties and invariants and go for automated testing.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKaiView Question on Stackoverflow
Solution 1 - Unit TestingS.LottView Answer on Stackoverflow
Solution 2 - Unit TestingKylotanView Answer on Stackoverflow
Solution 3 - Unit TestingJason WilliamsView Answer on Stackoverflow
Solution 4 - Unit TestingFrancesco CarucciView Answer on Stackoverflow
Solution 5 - Unit TestingMartin OmanderView Answer on Stackoverflow
Solution 6 - Unit TestingMel GeratsView Answer on Stackoverflow
Solution 7 - Unit TestingslartibartfastView Answer on Stackoverflow