What are the key principles of “Test Driven Development”?

The other day I was talking about Test Driven Development (‘TDD’) like one talks about a favourite football team or a popular artist. However, It was only halfway through the conversation that I realised that I would struggle to explain TDD to non-techie people and that it would be good to delve a bit deeper into the underlying principles of TDD:

  1. Write tests first  In more traditional software development methodology, the focus is on writing code first and then test it afterwards. Test Driven Development intends to throw that order out of the window; developers are expected to write a test first, run the test and then write more code.
  2. Write enough code to fail the (first) test – As outlined in below diagram (Fig. 1), the idea is that when testing a ‘first development’ you write a quick first test and make it pass with the simplest change to the production code as possible (this is often referred to ‘test first development’ or ‘TFD’).
  3. Subsequent code updates and testing (1) – The outcome of a test is either ‘red’ or ‘green’. Depending on the result of the test, you then make a little change in the code (refactoring) and run the test again. If a test has passed (i.e. shows as ‘green’) you can refactor from a green test to another green test. Following a refactor, if all tests are green, you then right your next failing test. A commonly used formula to represent this approach is: TDD = refactoring + TFD. 
  4. Subsequent code updates and testing (2) – What it effectively comes down to is a continuous cycle of writing a failing test (‘red’), making it pass (‘green’), move to the next failing test and then change the code of this test (refactor) to make it pass (see Fig. 2 below).  
  5. It’s about testing, not about writing specs! – I guess the main thing to stress is that TDD is NOT about writing detailed specifications. However, I spend quite a bit of time working with business stakeholders to specify scenarios on how a system is expected to work. This helps in creating a shared understanding of how functionality is (or isn’t) going to work, but – again – is not about capturing the scope of the functionality in painstaking detail, it is much more about driving the architecture of the code.
  6. Acceptance testing to prevent new software bugs – If you are a developer, the main aim is to write and run continuous tests to uncover any new – functional and non-functional – bugs and see if any changes or enhancements made resulted in faults or bugs.
  7. It’s a collaborative process – TDD specialist Gojko Adzic stresses the collaborative nature of TDD. The number of people that actually need to be involved depends very much on the nature of the product. For instance, if you are working on a new product or feature then it would be a good idea to have regular small workshops with the “Three Amigos”; a developer, a tester and a business analyst.  In contrast, when the product is more mature it might just be a case of pairing two developers to work on it.
Main learning point: one of the key things to remember about test driven development is its radical departure from traditional software development. Rather than writing all the code first and then doing tests at the end, the main goal of TDD is to let the tests do the work for you, to drive the structure of the code. What I like most about TDD is its iterative nature, following the continuous  ‘red-green-refactor’ loop, which enables developers (and the business) to discover any issues or bugs early on in the process.
Fig. 1 - The different stages of Test Driven Development
Fig. 2 - The continuous 'red-green-refactor' loop

Related links for further learning:

http://www.agiledata.org/essays/tdd.html

http://en.wikipedia.org/wiki/Regression_testing

http://www.threeriversinstitute.org/blog/

10 thoughts on “What are the key principles of “Test Driven Development”?

  1. Hi Marc.

    Good post.

    Just a small note: depending on the point of view, you could say that refactoring can help you make a test pass. However, in the context of TDD, we developers don’t normally refer to refactoring as the step to making a test pass.

    So, if it is: (1)red -> (2)green -> (3)refactor

    To go to (1) you need to write a test that fails. To go from (1) to (2) you must make the test pass. And then, whenever the test(s) passes, you can refactor the code safely to make it more understandable, cleaner, smaller, but without breaking the test (otherwise you would have gone back to (1) again).

    Thing is, once you are in (2), you normally commit your changes, to be in a checkpoint where all is good. From there, you can take the risk to refactor the code with confidence because, if you break the test, you can safely revert your changes and go back where you committed the last time (or fix your refactoring in case you think it’s easier).

    So, refactoring in the context of TDD, doesn’t mean “fix the code”, but actually “improve the code”.

    • Hi Andres,

      Many thanks for your comment, really helpful. I guess the main thing that your comment highlights is that TDD doesn’t intend change the intended behaviour of certain functionality but does aim to improve the quality of the underlying code.

      Cheers,

      Marc

  2. Yes, but it’s not its main purpose.

    What I mean now is that what TDD really tries with its rules is separate your work in phases to be able to focus on what you’re really doing in each step.

    It’s kind of like this: http://en.wikipedia.org/wiki/How_to_Solve_It although it doesn’t map 1:1, but:

    1: Understand the problem == write the test (the acceptance criteria of what you want to achieve)
    2: Devise a plan == think about how to solve it with the minimum amount of change required (ideally pairing with another engineer to have the best of two possible solutions)
    3: Carry out the plan == write the code and run the test, if the test passes you’re done, if it doesn’t pass, fix the code and re-run tests again and so forth; when this phase is finished, commit (checkpoint)
    4: Review/extend == improve your code, without changing behaviour (or, if you change behaviour, the tests you wrote in phase 1 help you know that you don’t break anything in this phase)

  3. […] “We don’t launch on date, we launch on quality” – I guess not all businesses have the luxury of not having too worry about deadlines – think of companies that have to oblige contracts or other time-led constraint – but Spotify clearly seem to value quality over time. I guess the main point of this principle is the focus on quality above anything else. The challenge for any product person and developer is to strike the right balance between releasing early and often AND launching quality products. For instance, at 7digital we aim to release continuously whilst making sure that every singly release is fully tested to ensure set quality standards (I’ve written about this practice earlier). […]

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