Test-driven development: structuring workflow

Test driven development (TDD) is perceived as being much more difficult than writing programs without tests. It’s true that it is more difficult. It’s not true that it’s much more difficult.

It is, however, a skill and it must be learned just as any other must be learned.

Having tools helps. Many modern scripting languages such as Python and Ruby have testing tools built into the language or in standard libraries. With other languages, such as c or c++, some effort must be made to set up an appropriate tool chain. This tool chain usually require using either pre-written libraries, or writing the necessary test infrastructure internally.

At least as important as having useful tools is creating the right habits for test driving coding. These test-first habits live in your workflow.

Structuring workflow

Learning how to do anything once is not that hard. Mastering the practice of a discipline requires building effective habits. For example, many people have exercise equipment at home, and know how to use it. But they go to the gym instead, where they find context, motivation and inspiration. The habit is at the gym, not at home.

While motivation and inspiration can be elusive, creating an appropriate context is mechanical. It’s as easy (and difficult) as creating an appropriate set of habits. Here are a few habits I’ve found useful for practicing test driven development:

  1. In your editor of choice, always open spec or test files in a known buffer which you can get to with a keystroke or two. I’m currently using vim, so I always know that the file containing tests is in buffer 1: ESC:b1 gets me there in a flash.
  2. Use a repl like irb or pry to check syntax. This is more helpful than it first appears. It takes the place of all those puts and prints. If you’re working with a compiled language, write stupid simple standalone programs to check behavior. This can as efficient as cat-ing a program into gcc from the command line.
  3. Always commit a test first, or never less than a test in parallel with new code. Never commit untested code. This is not the same as never pushing untested code.
  4. Scope objects and internal API in the test or spec file and build your functionality in the test file first.
  5. More? You tell me, comments are open!

Following these rules helps me create a workflow structure conducive to TDD.

Good tests are fungible

Over time, good programmers build up a library of working code which gets ported from project to project.

Having a library of test code makes this even easier. Instead of messing around with the code, port the test code first. It’s much more fungible.