The onset of infection


I've spent the morning doing test driven development, properly; writing tests first and everything. It works, it's faster and it's addictive.

The current work item for the online game is to take the existing game play and adjust it to include a few of the more complex special cases. This alters the game play a little, it alters who goes first, etc. It took a while for me to elicit enough detail to fully understand the requirements, but now I have it.

The changes are required in the game engine. I've already spent some time writing tests for this code, so although my test coverage for this project is pretty thin I do have some coverage here.

First thing this morning I added some code to the game engine ran my tests and they failed, as expected. The output in the logs from the mock objects no longer matched the expected test results. I checked the logs, fixed the tests and wrote a test for the new change. Still not test first...

Then I wrote another test. Due to the way the tests run off of the logs from the mock objects it's time consuming to adjust the expected results and then run the test. It's easier to run the test, look at the actual output, check that it's correct and then update the expected output with the actual output. So that's what I did.

The output wasn't correct. I fixed the game engine. Ran the test, checked the output. All was well, so I updated the expected output and ran the test again. Test passed.

I wrote another test... Added functionality. Wrote another test...

And I've been doing that all morning. I've not needed to run the server. I've done tests with 4 players that would have taken ages to set up by hand; start server, start client program 4 times, log in 4 times, manipulate game to the point that I need to test, etc... I think I can make all of the changes that this stage requires without running the server or client at all... Amazing. Already I've produced more working code that I would have expected.

The logs are complicated to look at. Some represent all the output that would normally be sent to the players; so we have, say, 4 logs for player actions. Then there are a couple of internal objects that we've mocked up; the database, the dealer, the game manager. But it means that you can see exactly what the test causes the game engine to do.

At the rate I'm going I expect that I will start to write the logs straight into the tests pretty soon. I know what I'm expecting to happen. I should be able to write the test and adjust a previous log to include the new stuff that this test tests. Run the test and watch it fail. Add the code to make it pass. Run the test and watch it pass. Move on.

A month or two ago I would have sworn that this code was 'impossible' to test. The server is a multi-user game server that is driven by player actions and internal timers. How can you test that... It's easy, you try and write a test and decouple the code to be tested until you can. Slip in a few interfaces, mock up a few service providers, remove all traces of singletons, parameterise from above. Then just drive the code from the test harness...

Muchos coolio, how did I ever work any other way...

Leave a comment