Test-Driven Development (TDD) is a fundamental practice in the Extreme Programming methodology. The concept behind it is that before you write code to meet a requirement, write a test that, when it passes, proves the requirement is met.

For example, let's say you have a User and when that user does something bad, they get locked out of their account for 24 hours, and if they try to log in, they get a message that says that they are locked out.

Using Test-Driven Development, we would first start with a Test. Given the above requirement, our test might look like:

[Test]
public void badUserIsLockedOutAtLogin
{
  User user = new User("Bad User");
  user.MarkAsBadUser();

  Login loginAttempt = user.Login("password");
  Assert.IsFalse(loginAttempt.Successful);
  Assert.Equals("Sorry, you are a bad user and your account is locked", loginAttempt.ErrorMessage);
}

(Quick overview. The [Test] marks this as a Test in C#. The Assert.IsFalse and Assert.Equals are methods that, if fail, cause the entire test to be marked as a fail and display as a red bar if you are using a GUI runner)

Our goal now is to do the simplest thing possible to make this test pass. In fact, in it's current state, the test probably doesn't even compile, because your User object may not have a MarkAsBadUser() method. So you add it.

Once you added the method, you find the test fails because the Login object doesn't take into account if the user is a bad user. So you add that. Then you add the code to produce the error message.

Now, you've added the code for the feature, and your test passes. Not only do you have the feature added, but you have a test that proves it, and the same test acts as a safety net for regression testing as you make future modifications to the code.

The key points to TDD are:

The entire process is also called Red, Green, Refactor named after the pretty red and green colors that the GUI test runners (like JUnit and NUnit) display with failing and passing tests.

Some other key points:

  • Test Everything that could possible break - Generally this means that simple getters and setters aren't tested unless there is actual business logic in them
  • Refactor only on a green bar - these Unit Tests should run at 100% green at all times. If you are changing code not related to a failing test on a red bar, you don't have your safety net

There are frameworks available for just about any language one can think of, including C#, Java, Javascript, PL/SQL, Ruby, Python, Perl, C++ and many, many others (Including DUnit, the Delphi version of the xUnit framework (thanks StrawberryFrog!)).


Resources:
  • http://www.objectmentor.com/writeUps/TestDrivenDevelopment - an overview of TDD by Object Mentor
  • http://www.testdriven.com - A site dedicated to TDD resources
  • http://en.wikipedia.org/wiki/Test_driven_development - Wikipedia article on TDD