I first wrote about Agile development as a lone indie years ago. I got some good comments, but it still felt like I lacked any real insight into how to be a better developer on my own. A couple of years later, after seeing someone use unit tests first-hand, I wrote about Test-Driven Game Development.
So I immediately tried to use unit tests for my next project, which was my Ludum Dare #12 entry. I stopped after encountering difficulty. I didn’t know what I was doing, and I needed to make progress. I had a deadline.
Recently, I decided to start using TDD to create a simple game. And I wanted to use it for the entire project, not just the easy parts. I created a simple design for a game involving vampires, and set to work.
And immediately I hit a problem. In order to get anything useful on the screen, I needed to use libSDL. How do you go about writing unit tests that make use of a library? I don’t want my test binary to open and close windows, manipulating hardware, and otherwise resulting in weird side effects. Ok, no problem. I’ll just create an abstraction layer between the game and libSDL. I called it HardwareLayer, but then ran into another problem. The HardwareLayer would need to use libSDL directly, so all I’ve done is put the hard-to-test code in a new class. Well, maybe I can make an interface, but how does one test-drive his way to an interface? I didn’t make anything easier for me at all. Unfortunately, my lack of experience was going to bring this TDD experiment to a standstill.
But I pushed. I checked the book Test Driven Development: By Example but couldn’t find any information specific to what I was trying to do. I tried to find a TDD-centric IRC channel, but none existed that I could find. So finally, I threw out my question on Twitter, and within moments, I had a response from an expert.
Brett Schuchert of Object Mentor took the time to write up a blog post on TDDing an Interface. While his example was in Java, it was eye-opening to see how TDD gets done in a somewhat real-world example. I was able to make some progress, but still had the problem of using libSDL at some point. My inexperience questioned whether I would be using unit tests on the code that simply delegates to libSDL calls.
And Schuchert once again spent an evening writing up another blog post about hiding global methods, and this time he even used C++ and created a working project! He claims that the effort to get everything under test was simple to do since most of the issues I was having are idiomatic and therefore pretty easy to solve.
In our discussions in email, Twitter, and the blog, I had the insight I needed. I’ve since purchased Working Effectively with Legacy Code since a number of the issues I had involved dealing with untested/untestable libraries. If it is so idiomatic, I should know it, too. The book would have been very helpful with issues I’ve tried to deal with in the past, so I look forward to applying my new knowledge going forward.
Since those posts, in the time I’ve been able to dedicate to game development, my test binary doesn’t make calls to SDL directly, and my actual game does. I might still do bizarre things when it comes to TDD and unit testing, but I’m making progress that I’m reasonably confident is correct and working at all times. It helps that I recently participated in a three day TDD workshop that the Day Job sent me to, but I found that the most beneficial part was doing exercises with someone available to say whether or not I was going about it correctly enough. In fact, even the Bowling Game Kata makes a lot more sense to me as an exercise. That is, I get it now.
4 replies on “Learning How to Unit Test”
Could you post some code examples of what you are doing? I’m curious!
I knew someone was going to ask for some code! Unfortunately the project isn’t doing much right now, and I’d like to get a bit more significant work in before I post it. When I release the game, I’ll also release the source.
In the meantime, I might have some earlier releases to demonstrate how TDD has been helping.
You should really take a look at Noel Llopis’ (www.gamesfromwithin.com) articles on TDD for games, if you haven’t already. Although his blog has become an ad for Apple ^H^H^H^H^H^H iPhone development blog, in the past he wrote a good deal of interesting articles on software architecture.
Honestly, its not worth testing any of the SDL wrapper stuff unless its non-trivial. Write tests for new code and non-trivial code. In your case its probably mostly game play code, and higher level rendering code. Ensure you are drawing the right sprite and frame of animation, don’t worry if you’ve called glVertex enough times.
That said you might want to create a mock HardwareLayer object that keeps track of it’s own internal state. Then you can verify that your code properly set the right render state, but that’s probably overkill.
[…] GBGames’ blog also has a post about Learning How to Unit Test […]