As long as you are writing your tests before your code and doing regular refactoring, you are doing TDD !
The Red – Green – Refactor loop is useful to introduce TDD to new developers. Different loops can be more effective in real world situation.
The Red – Green – Refactor loop is not a dogma !
Refactor – Red – Green
When I work on a story, I very often keep a TODO list next to my desk. I use it to keep track of the next steps, the edge cases to test, the code smells and refactorings to do.
When I get to the end of the story, all that remains of this list is a few refactorings. Very often, I don’t do them !
With the feature working, doing these refactorings feels like violation of YAGNI. Next time we’ll have to work on this part of the code, we’ll have a story to serve as guide to which refactorings to do.
The same thing is effective at the unit test scale. It’s easier to refactor when you know the test you want to add. Refactor to make this test easy to write !
Here is an example with Fizz Buzz
1 2 3 4 5 6 7 8 9 10 11 12 13
Here is the test I’d like to add.
1 2 3 4
Unfortunately, fizzBuzz needs to return a String instead of an integer for it to compile. That’s when I would refactor before adding the new test.
1 2 3 4 5 6 7 8 9 10 11 12 13
In the end, this loop is very like the classic TDD loop :
A bit more YAGNI, that’s all.
Red – Better Red – Green – Refactor
A few weeks ago, I wrote about error messages in unit tests. To summarize, extra work on error messages reduces the testing feedback loop.
We can translate this focus on error messages into an extra TDD step. Whatever the TDD loop you are using, you can add this step after the Red step.
Red – Green – Refactor – Red – Green
Sometimes, it makes sense to refactor before fixing the test. The idea is to rely on the existing tests to prepare the code to fix the new test in one line.
Let’s take our Fizz Buzz example again. Imagine we finished the kata, when we decide to tweak the rules and try Fizz Buzz Bang. We should now print Bang on multiples of 7.
Here is our starting point :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
I could go through all the hoops, 7, 14, then 37, 57 and finally 357 … By now, I should know the music though !
What I would do in this case is :
- first to comment the new failing test to get back to green
- refactor the code to prepare for the new code
- uncomment the failing test
- fix it
In our example, here is the refactoring I would do
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
From there, fixing the test is dead simple.
In practice I find this loop very useful. At local scale as we saw but it’s also a great way to refactor your architecture at larger scale.
One downsize is that if you are not careful, it might lead to over-engineering. Be warned, keep an eye on that !
Last caveat : not all TDD interviewers like this technique …
It’s not because you are not following the Red Green Refactor loop to the letter that you are not doing TDD.
An interesting point is that these variations to the TDD loop are combinable ! Experienced TDD practitioners can jump from one to the other without even noticing.
This paper argues that as long as you write the tests along (before or after) the code, you get the same benefit. That’s not going to make me stop writing my tests first, but it is interesting. That would mean that even a Code – Test – Refactor loop would be ok if it is fast enough !