May 17 2007

Notes from RailsConf 2007 – Test-Driven Development

The Testing Conundrum

We all know that testing is necessary, but when a deadline is approaching (and/or a client wants to look at the latest release with those new features implemented) we might not all do the testing that is necessary or do all the testing that is necessary. Speaking personally now, there have certainly been times when I would have liked to write those extra tests but haven’t been able to take any minutes away from writing code that will directly lead to new functionality. I am relatively new to test driven development (TDD) and we can certainly argue over whether implementing tests will directly lead to new functionality, but in the end, the client typically will not see the tests or the results of the test code (if we exclude the point that the application functioning correctly is a result of the tests). But for a moment, let us put all this hypothetical arguing behind us and focus on the topic at hand, TDD. In David Chelimsky’s Intro to TDD tutorial I was thoroughly re-convinced that building with tests in mind is not only needed, but essential.

When doing TDD you have a higher level of assurance that your application is doing what you have designed it to do, and when it passes your tests you can be sure that it does what you are testing it for. More importantly, using TDD will lead to increased maintainability in your code because (1) when you modify your code base, and a test fails, you have an instant notification that your modification is breaking the code and some idea where it is breaking it and (2) when someone is looking over your code, and needs to understand the functions it is performing, tests will serve as a form of documentation. As a corollary to maintainability, writing code using TDD should lead to a cleaner code base, where cleaner intends accomplishing its specified functionality without excess.

Getting Started with TDD

TDD can be done using the following algorithm:

  1. Write a test that will fail.
  2. Write code that will make the test in (1.) pass.
  3. Eliminate duplication in the code by refactoring.
  4. Go to step (1.).

The algorithm is simple enough assuming we know how to refactor code. While writing test code we must remember that the goal of the code is to produce an application that conforms to the specifications we have been given. This entails that if we find ourselves writing code, the sole purpose of which is to enable a test we have written to pass, we are doing something wrong. The idea behind what we do in TDD is to write code from the perspective of a client, not a computer!