Here I have put together what I like to call the Ten Commandments of Test Driven Design, ten basic behaviours that should be followed when we are going about our TDD day.

1. THOU SHALT WRITE THE ASSERTION FIRST

Ask the question you want to ask, before trying to think of how to answer it. If you write the assertion first, you know exactly what it is you’re aiming for.

2. THOU SHALT RUN THE TEST TO SEE IT FAIL BEFORE WRITING THE IMPLEMENTATION

Check that what we’ve written actually tests what we want it to. Does it fail in an informative way? Does it fail for the reason we want/expect it to? If we jump straight to the implementation we have no idea whether we’re actually asking the right question.

3. THOU SHALT WRITE TEST NAMES WHICH ACCURATELY REFLECT THE SPECIFICATION

Your test should act as your documentation. Down the line, someone modifying your code would rather be told that ”ableToSendPotionToWizardUsingAddress” failed, rather than ”testCreateAndSend” failed. When the tests read like a specification, we are getting across the exact intent of that test without the need for pesky comments littering our otherwise beautiful code.

4. THOU SHALT USE TRIANGULATION

Triangulation is the process of incrementally adding to the implementation by adding more and more tests, and slowly adding code to pass each one. This is best illustrated through an example, so I’ll just go right ahead:
Let’s say we are attempting to write a method returning the sequence of the first 20 elements of the Fibonacci sequence:

4c42de46d22d22305c59b9ba88e387e9

We could do the following:

  • test that the element at position 1 of the sequence is 0
    • return a sequence of 0s
  • test that the element at position 2 of the sequence is 1
    • return a sequence where each element is its position – 1
  • test that the element at position 3 of the sequence is 1
    • if(position != 0) return 1 else return 0 in the sequence
  • test that the element at position 4 of the sequence is 2
    • return a sequence where each element is floor(position/2)
  • test that the element at position 5 of the sequence is 3

As you can see, each step fulfils all the tests in the simplest way possible at this stage. We only begin to generalise further when we have another test case that requires it – until we aren’t pushed to implement something we should not think about doing so.

5. THOU SHALT KEEP THE TEST SEPARATE FROM THE IMPLEMENTATION

This just separates the tests from the main body of the code for any other viewers of the code. It keeps things organised and easy to figure out.

6. THOU SHALT HAVE INDEPENDENT, MUTUALLY EXCLUSIVE TESTS

Our tests should all be able to be run in any order, completely independently of one another. There is no point having multiple tests which could all fail for the same reason. For example, if we were testing a method which returned a list of all wizards and witches to be sorted, alphabetically by surname, we could test the following:

  • first element of list is Hannah Abbott
  • first and second elements of list are Hannah Abbott and Susan Bones
  • first, second and third elements of list are Hannah Abbott, Susan Bones and Terry Boot

and so on.
However, if the first element of the list is not Hannah Abbott, ALL these tests will fail. Instead, we should test:

  • first element of list is Hannah Abbott
  • second element of list is Susan Bones
  • third element of list is Terry Boot

and so on.
These tests can be run independently, and in any order, and will fail for the right reasons (if they have to)

7. THOU SHALT ORGANISE TEST CODE TO REFLECT HOW THE IMPLENTATION IS ORGANISED

Because that’s just a nice way to do things. It just makes it all a lot more readable and easier to follow.

8. THOU SHALT ALWAYS KEEP TESTS UP TO DATE

Tests serve as your documentation, and as such must be updated along with any new implementation. If a piece of functionality is added/modified/removed, the relevant tests should be added/removed/modified accordingly.

9. THOU SHALT WRITE TESTS WITH ONLY ONE REASON TO FAIL

That way, when they do fail we know exactly why, and debugging time is hugely reduced.

10. THOU SHALT NOT REFACTOR WHEN TESTS ARE FAILING

Our tests act as a safety net for our refactoring. If we have failing tests, we have no way of knowing that the refactoring we have done hasn’t actually broken the code. What if our new implementation breaks the failing test in a different way? FIX THE TEST FIRST!

These are the best habits to get into in order to run a long, healthy, prosperous TDD way of life. Happy TDD-ing!

<<<< TDD: An Introduction                   >>>> TDD: An Example

Advertisements

2 thoughts on “TDD: The Way To Go (The Ten Commandments)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s