Today I feel like coining a new term. I should admit I love creating contrived neologisms, casually using them in front of friends and coworkers and see if they spread1.
The term I want to introduce is no less than a variation on test driven development. But first, let’s roughly sketch the standard TDD workflow just for the record:
- Red phase. You should start by writing a bit of test code, just enough to fail. This is the red phase because failed tests bring you cheerful red lines to your terminal.
- Green phase. Then you should add just enough production code to make the tests pass again. It is important to stick to this rule to avoid having untested code.
- Yellow phase. As you have previously focused on what the code should do you might have introduced duplication or other code smells. Now, you can refactor at will with the peace of mind that only a comprehensive suite of tests can provide. Then, rinse and repeat until your feature is complete.
The variation of TDD I want to baptize is practiced by people convinced of the value of unit tests, of high coverage and even of the less popular practice of interleaving test and production code. However, this fellows don’t take seriously the test-first practice so this is their workflow:
- Green phase. They write some production code. How much? A reasonable amount, sometimes the whole module if they feel adventurous. All green at this point as no test is failing.
- Green phase again. Then, they write some tests trying to cover representative cases for the freshly written production code. You might be surprised by an occasional failing test but you get green again.
- Yellow phase. Finally, they refactor as in the standard TDD and repeat if they managed to not to write the whole production code yet.
With this setup you get part of the benefits of the standard TDD but with some problems that can be painful and let people think that the original practice is broken2.
When you write production code first, you might be written the wrong assertion. You might make a mistake and “test” something that is always true regardless of whether you add the right behavior. Even worse, you could be asserting just the opposite of what you desire and you would not notice as you are not expected to see the tests failing at any point.
You will also have less comfortable APIs, as you designed while focusing in the implementation, not on the user code. Test-first design is also a powerful force toward more decoupled designs and you won’t feel that love, neither. In fact, by the time you will write the test cases, you will be tempted not to test the most contrived cases.
In this line of thought about design, but more subject to personal opinion, I think that when design is done in huge leaps instead of tiny steps the result tends to the over-engineering. Trying just to pass one test at a time is a constant remainder of the YAGNI principle.
How we should call this “disordered” TDD? Green-green-hope-for-the-best is too long so I’ve decided to mirror the letters and use DDT because:
DDT is great for killing bugs but be prepared to risk your health.
An ad from Time Magazine (June 30, 1947). DDT was still cool.