Hardcore Test Driven Development

tdd as if you meant it

One of my favorite sessions in the coderetreat format is the "TDD as if you meant it" kata. It really gets you thinking about the huge difference between test first development and 'real' test driven development. This is one of the most difficult formats to explain to participants joining the coderetreat for the first time. So I thought it would be a good idea to share with you how I explain and use this technique. The flow for this looks easy enough when you just read through it:

  1. Write one failing test

  2. Make it pass by writing implementation code in the test method

  3. When duplication is spotted extract implementation from test to:

    1. a new method in the test class

    2. an existing method in the test class

  4. When more methods belong together extract them into a new class

  5. Refactor as required

But let's take a closer look at each step. Write one failing test Ok, I admit. This is the easy part. Or is it? Determining what is the most useful next (or first) test to write is not that easy. I'll give you one option and I'll come back to this in another future post. If you start by writing an end-to-end acceptance test for your new feature, it will help you to discover which steps to take to implement it. More about that later. For the sake of simplicity I will use a the example of adding two integers. I know it's kinda lame but I promise that I will record a video soon which will demonstrate the flow of this technique using a more interesting example.

failing test

Make it pass by writing implementation code in the test method

You say what? I need to write my 'real' code inside my test method? Yes, that's exactly what I want you to do. Think about the famous line "first make it work, then make it pretty" and use that mindset to wrap your head around this idea. First make your behavior work, then figure out to which method or class this behavior belongs. One little tip to help you do this is to really use the 3A pattern: Arrange Act Assert. If you consistently use this, it will be easy to see what the real Act is and this will help you to extract this afterwards. In our example we first Arrange the two variables we need to add. Next step is to set up the container for the result of the Act and we close of our test with Asserting our assumption.

make it pass

When duplication is spotted extract implementation from test

If you don't have any duplication, you just leave the implementation in the test for now. This will force you to write a new test for the same behavior. Once you have this second test you will see the duplication more clearly. Looking at our example we have both tests returning a number from our Act which seems related to the two numbers ;-)

duplication

We can now extract this behavior to a separate method in our test class. Are you kidding me? Still keeping the 'real' code in the test class? I am not kidding you, we still leave it in there until we feel confident that our tests have given us enough information to decide to which class this behavior or this set of behaviors belongs to.

extract method

When more methods belong together extract them into a new class

Once you have a set of behaviors that clearly belong together in one unit of work, you can extract these methods into a new class. A class is nothing more than a concept that allows us to group behavior that is related.

Refactor as required

This is something you do every time you have a green test. Don't wait to refactor until everything is done or finished, you won't have the discipline to actually do it. Think about doing the dishes. When it's only dishes from one meal it is just a small effort. While if let it stack up for a couple of nights it's a huge pile of mess and you get demotivated even looking at it. Feels familiar when we think about code as well right? I would like to thank Keith Braithwaite for introducing this idea for the first time and Adrian Bolboaca for introducing it to me. Stay tuned for more info about this technique for my soon to be first coding video.