Thinking Test-Driven
Those who want really reliable software will discover that they must find means of avoiding the majority of bugs to start with, and as a result the programming process will become cheaper. If you want more effective programmers, you will discover that they should not waste their time debugging, they should not introduce the bugs to start with.
—Edsger W. Dijkstra, The Humble Programmer (1972)1
The mechanics of Test-Driven Development (TDD) are simple, but TDD is not an invitation to disengage your intellect, nor does it require you to forget your own previous experiences and education.
People naturally talk about software behaviors using examples, though they aren’t always aware that they’re doing so. While working with a team, I will often hear someone offer a simple example in a verbal sentence or two. By capturing that example in a small bit of automated, executable specification (a test), the team can be sure of the following:
The example doesn’t get lost in translation later.
Once complete, the implementation works correctly.
The behavior captured by that example is never mistakenly broken during the entire life of the product.
For developers, many examples will occur to them while they are writing code, but that dialog is often internal: “What do I want my next few lines of code to do?” Before a developer writes even the tiniest bit of logic, they already know what they expect that code to do. TDD asks the developer to record that thought by turning it into a concrete description of the example and its expected results.
This book encourages a deeper dialog: “What if a caller does this? What do I want the software to do? How can I be sure I got it right, and that I don’t break something else?”
Writing that thought in a familiar language and having it instantly added to an automated test suite costs the developer very little extra time and could easily save them hours upon hours of debugging later.
The Safety Net
The team’s collection of fast, automated, and comprehensive tests that grow from a diligent TDD practice is much more than a typical suite of tests. For the test-driven team, the test suite is a powerful safety net.
Although each tiny individual unit test might seem quite simple by itself, in the aggregate that safety net protects the team’s entire previous efforts and the business’s investment in the software produced. Whereas individual tests instantly catch common mistakes in implementation, the comprehensive safety net also protects against mistakes during refactoring.
