A culture of 100% test coverage has grown up around TDD. Code quality “measuring” tools such as Clover are used as a pugil stick to beat developers over the head with, if their code doesn’t measure up to an arbitrary set of metrics: and one of these is a measure of how much product code is covered by unit tests.
(Clover does have some pretty awesome features by the way, such as test optimization; but institutionalising test coverage as a measure of code quality isn’t one of them).
TDD itself can become a highly elaborate, labour-intensive way of creating code. It’s not uncommon to end up with far more test code (which the customer never gets to see, and which arguably doesn’t really “do” anything) than product code, which is what the customer is really paying for. Yes, the customer is also paying to have product code of a sufficient quality, and that’s what TDD addresses. But there has to be a better way of improving code quality with tests: a way that doesn’t soak up developers’ time and turn the tests into the main software deliverable, in the developers’ minds.
There are three main shortcomings to TDD:
- It’s too time-consuming
- You end up with too much test code, with code paths duplicated by different tests
- The final amount of test code and product code that you see is disproportionate to the amount of refactoring/evolutionary design that went on to get there
To sum these three issues up: TDD is Too Damn Difficult; it takes too much effort to produce a bit of “production code” result.
Not using TDD – just writing tests after you’ve written some code – also has problems, in particular the aimlessness of this approach. It’s difficult to know when you’re done writing enough tests – in practice there won’t be enough time to hit 100% coverage, so the team must stop at some arbitrary timeboxed stage somewhere along the road. Most dissatisfying.
So here’s the idea. These shortcomings can all be addressed by first doing a small amount of structured up-front analysis and design, and identifying which parts of the code you’ll gain the most benefit from testing. We call this approach Design Driven Testing or DDT (the linked tutorial illustrates how to use an add-in for Enterprise Architect to automate much of DDT).
Take this sequence diagram, an overview of the code path for a hotel search (click the image for the full-size version):