In “TDD Guided by Zombies”, James Grenning shares a seasonally-appropriate acronym for developing unit tests — just in time for our class to wrap up its unit testing section! ZOMBIES stands for Zero, One, Many/More, Boundary behaviors, Interface definition, Exercise exceptional behavior, Simple scenarios/Simple solutions. The first three letters (Zero, One, Many) describe, in order, the complexity of the behavior undergoing testing — for example, a queue with zero, one, and then many entries. The second set of letters (Boundary, Interface, Exercise Exceptions) give the order in which to build test cases — start with boundaries, design the interface undergoing testing (or ensure that the code meets the interface requirements), and then test exceptional behavior. The last letter tells the tester to create simple scenarios with simple solutions — add the minimal possible behaviors to production code in order to pass the tests generated by the first six parts of the acronym.
Grenning spends the bulk of the article on an example of a circular queue implementation in C++, showing how he progresses through each step. He gives clear examples of both what to do and not to do. However, I’m more concerned with the underlying principles and process, so in the interest of brevity I’ll skip a detailed review of his example and simply say that it’s thorough and worth a longer period of study.
I chose this article not just because of the season (or that it coincides neatly with our in-class work), but because it helps to answer the question of how. We’ve learned many methods for generating unit test cases, but how do we pick the order? How do we work backwards from tests to code in a way that makes sense and satisfies the specification that we’re handed? This confirms what I learned in 343 last year: ZOMBIES are the key to TDD and to successful unit testing.
And what can I, as a learner, take away from this? Firstly, and perhaps most trivially, it can help to wrap important concepts in cute acronyms. It makes sharing and remembering knowledge easier. Secondly, it clarifies the most important sets of values to test, and the most important times at which to test newly-instantiated objects (or other language-apprpriate constructs): when they are fresh and empty, when they have a single value, and when they contain many values. Thirdly, the article really drives home the importance of minimalism in testing and test-driven coding. If a simple solution is all that it takes to meet the specification, then use it. If a complex solution can be simplified, simplify it.
This semester and onward, when I need to develop unit test cases, I’ll be thinking ZOMBIES.