Generating Languages Via TDD
By Adrian Sutton
As you spend more and more time developing good unit tests as part of TDD, you regularly find yourself writing the same thing time and time again. Fortunately, TDD also includes a refactor step to remove this duplication again. I’ve found it quite interesting that over a few weeks of this, we’ve actually developed a complete language for asserting the correct output. For example:
assertStartTagSpec(HTML.Tag.HTML);
assertStartTagSpec(HTML.Tag.BODY);
assertStartTagSpec(HTML.Tag.P);
assertContent("Hello World!");
assertLineEnding();
assertEndTagSpec();
assertEndTagSpec();
assertEndTagSpec();
assertEndOfSpecs();
Even without the domain knowledge, it should be fairly obvious what is expected. It’s definitely a lot clearer than:
ElementSpec spec = specs[0];
assertEquals(ElementSpec.StartTagType, spec.getType());
assertEquals(ElementSpec.OriginateDirection, spec.getDirection());
assertEquals(HTML.Tag.HTML, spec.getAttributes().getAttribute(AttributeSet.NameAttribute));
spec = specs[1];
...
Notice how even the specs array and the current offset within it is hidden. The human brain naturally identifies the code as a progression and so the extra clutter just gets in the way. Over time we’ve added all the different variants of these methods that we need by overloading the methods so that we can specify additional attributes etc, without needing to specify the default values all the time. The end result is that we can see the important parts more clearly and get to that green bar faster.