Computer programming is always evolving. Several years ago I encountered automated unit testing (i.e, the many Junit, CXXunit, etc. frameworks). Having a good test suite covering your back is confidence building. I started using it on CPIA (a re-implementation of PIA, the Platform for Internet Applications, a Java Web app framework, in C) about half way through. Translating Java to C can be a bit tedious, but after building some patterns, habits, and tools, it becomes rather straightforward. However, bugs, especially memory management bugs, can persist for months. Since I started writing tests half-way through, they tended to be added top-down, i.e., written for the newest code with additional tests for the older, lower level code written as problems were encountered and fixed. The experience convinced me further of the value of a good test suite.
Since then I have progressed to writing the code, testing it by hand, and then writing automatic tests.
Test-Driven Development (TDD) turns the order around: write the tests, run them (failure expected), then write the minimum code necessary to pass the test. Then write more tests and repeat until done. It is a hard habit to develop, but I am beginning to see the value of writing the tests first. One reason is if it passes on the first try, then something’s wrong! Either one of your colleagues has already done the work, the test framework (or your understanding of it) is broken, or you aren’t testing what you think you are. (Quis custodiet ipsos custodes?, roughly, who guards the guardians?) If your tests always pass, your confidence that your back is covered may be rudely shattered.
Behavior Driven-Development (BDD) is sort of TDD with the push of “you should” replaced by the pull of “I expect the code to behave like this”.
To illustrate, in an application I am currently writing (TagFlow, coming to a RubyForge near you soon), in the list of tasks, the task description is shortened to just a single line. In the task’s page, the full description is displayed. Recently when cleaning up code, I inadvertently shortened all descriptions in a misguided attempt clean up the API. (The same template is used for both versions of task, I just missed that the description as well as the complete task object was passed to the template because the description may have been shortened by a higher-level template).
I fixed it, added some comments to explain the more complex API, and pondered whether to write some tests. It looked like they would be a pain to write and brittle. Maybe more trouble than they are worth. I wasn’t likely to make that mistake again, was I?
However, from the BDD perspective, my course is clear. I should have an executable specification of how I expect the application to behave, even before coding it. Focus on what first, then work on how. So I am off to write a behavior specification using Rspec that indicates to a human reader the expected behavior and also tests for that behavior.