This post is based on Unit Testing and introduces the concept of Test-driven Development.
Test-driven Development, or TDD, is a practice where tests guide the development flow. Instead of just jumping right into coding, the developer first writes a failing Unit Test, describing a single, separated functionality. Developer then writes just enough code to make the test pass, refactors the code structure and verifies all the tests pass. The developer then continues to write the next test. This is called the TDD cycle.
The motivation for TDD is to drive the development outside the code and help creating a better design. In TDD you automatically think test-first (see Unit Testing), which means you concentrate on what needs to be done and verify the functionality at the same time.
What Refactoring?
Martin Fowler has described Code Refactoring so well that I rather guide you there:
Red - Green - Refactor

The TDD cycle is often called Red - Green - Refactor to better describe the development flow:
- Red: Write a failing test.
- Green: Make the test pass with as little coding as possible.
- Refactor: Eliminate duplication and improve the design.
In TDD it’s very important to first make sure the new test, and only the new test, is failing after Red. From the failing test you know there is a functionality missing. After Green it is as important to make sure all tests pass to make sure your code is working as expected. You can then proceed to Refactor where you remove duplication and improve the overall design of your code. As you now know all tests pass for your existing functionality, Refactoring is safe and you can change the code structure without the fear of breaking something.
Once you are happy with the code, you start the TDD cycle again with a new test.
How about Behavior-driven Development?
Many argue the example below is actually Behavior-driven development, a practice derived from TDD. The difference is that in BDD the system requirements are more strongly connected to the test cases and thus the tests create a stronger behavioral description of the software module.
In my experience quality code should be anyway understood by others, and the tests should describe the functionalities of the software in an understandable way. Thus I don’t like making a separation between these two terms.
Critic against Test-driven Development
This is the hard part. I personally feel that Test-driven development is a very important practice and every developer should have TDD in their toolbox. However, TDD is a very strict practice and often testing every line of code might prove to be impossible. I wouldn’t want to feel like a loser for not creating e.g. unit tests for threaded backend processes or skipping UI tests for the sake of already having Acceptance Tests in place.
As I already wrote in Unit Testing, the developers should always think test first, because that is one of the most important benefits of TDD - guiding the development from outside the code. On the other hand strictly writing tests first might occasionally decelerate or hinder the development flow.
Finally: An example of the TDD Cycle
I’ll use the familiar Roman Numerals (see Unit Testing) as an example. The examples have been written in Ruby and RSpec, but don’t worry, you will be able to follow the idea even without knowing the syntax.
1. Creating the module and testing 1 converts to “I” (Red)
Let’s start with the first failing test by creating the file spec/roman_numeral_spec.rb:
require "roman_numeral"
describe "roman numerals" do
subject { RomanNumeral }
it("should convert 1 to 'I'") { subject.convert(1).should == "I" }
end
And run it to make sure it really fails:
$ rspec
... `require': cannot load such file -- roman_numeral (LoadError)
2. Make it pass (Green)
As we don’t have the module nor one single line of code it is natural that the test is not passing. Now let’s continue to implement the code. Create file lib/roman_numeral.rb:
class RomanNumeral
def self.convert(arabic_number)
return "I"
end
end
And run the tests:
$ rspec
.
Finished in 0.00044 seconds
1 example, 0 failures
Perfect. Currently the code is not doing much, and there is not much to refactor, so we move on to the next cycle.
3. Roman numerals should return “II” for number 2 (Red)
Let’s add a new test to verify the converter returns “II” for number 2:
require "roman_numeral"
describe "roman numerals" do
subject { RomanNumeral }
it("should convert 1 to 'I'") { subject.convert(1).should == "I" }
it("should convert 2 to 'II'") { subject.convert(2).should == "II" }
end
And run the tests to verify only the new test is failing:
$ rspec
.F
Failures:
1) roman numerals should convert 2 to 'II'
4. Make it pass (Green)
Let’s write just enough code to make the new test pass:
class RomanNumeral
def self.convert(arabic_number)
if arabic_number == 1
"I"
else
"II"
end
end
end
And run the tests:
$ rspec
..
Finished in 0.00055 seconds
2 examples, 0 failures
5. Removing duplication (Refactor)
As we have now verified our system works as expected we can refactor the code to remove duplication, clean up the structure and make changes towards the final solution.
class RomanNumeral
ROOT_NUMERALS = {1 => "I", 2 => "II"}
def self.convert(arabic_number)
return ROOT_NUMERALS[arabic_number]
end
end
You can now proceed to finalizing the solution and sending me a Github Pull Request. Happy coding!