Since Corey is an experienced TDD practitioner I was honored that he’d given it a go, and was eager to see the video. Later, corey asks for my remarks on it, which i will gladly put here. In general, Corey’s video is a great piece of TDD work to watch as an example of a master TDDer doing his thing. Everything flows gracefully and the code produced is simple, readable and of course – works.
I especially loved the large amount of merciless refactoring Corey made during the Kata. As you TDD you should not cut any corners in the refactoring area – and almost after every passing test or two, Corey does refactoring to some very simple code patterns.
Another worthy note – Corey takes care in refactoring the tests as well throughout the kata. Kudos!
A few things that stood out for me can be thought of as very little things – and are mostly questions:
- Partial Test: at some point, Corey seems to be writing the tests incrementally as well, in that he writes an empty test that passes, and then fills in the test itself to see it fail (which is usually where I start). I wasn’t sure why he’d do that, but the reasoning could be that he wants to make sure the environment works for the test. since he does it all in Ruby, which is a more forgiving environment for typing errors, this might be it.
- Always passing test: very early on, in the second test actually, Corey creates a test that asserts that sending “0” returns “0” – which passes and never fails. That is because by default empty strings as input return zero. I do it a bit differently – i try to start with a failing test that drives more functionality, and if i can find a way to make a test for “0” fail as well to being, i will do it (so that i can ‘test the test’ in TDD style).
A different way: Don’t write a passing test for “0” input. instead write a failing test for “1” input. Another options would have been to indeed start with a passing test for “0” input, but then to go production code and deliberately return –1 to see the test fail, then fix it to return “0”, see the test pass again, and move on to the next test.
- Magic inputs: Corey sends in various seemingly random, out of the air numbers as inputs to the tests starting from the third test onwards. For example, to a reader who sees a test that says “sending in 5 returns 5” that reader might ask themselves “why 5? why is 5 so special? should I also use 5 in my tests?”.
A different way: To avoid such confusion i like to stick to the lowest common version of an input that still proves the application wrong. if sending in “1” produces the same result as sending in “5” then my all means i will send in “1”. If the input is 2 digits, I’d send in “10”, “100” and so on. If the input still does not make sense I would put it in as a variable named “SINGLE DIGIT NUMBER” to explain to the reader what is so special or not so special about this value.
The simplest Test:Corey wrote the tests for inputs with \newline characters without considering the most basic test for this kind: a simple string containing only a new line character (equivalent to an empty string). I agree that not everyone would pick up on this as an idea, since you might feel this is an invalid input into the system. nevertheless, when I teach TDD this is the way i teach the kata. It feels like a more natural incremental evolution of the code and tests, and a good way to send the message that anything can be divided into small increments if you want to.
Refactor to un-readability: At some point Corey refactors the code that handles delimiter characters into a single line of Ruby code. while it isa form of refactoring, i found that the code after refactoring was much less readable than it was before.
A different way: I try to avoid any “immediate if”s or single line “smart” statements that feel more “smart” than “simple”. When i have to choose between length and readability, i will choose length every time. this makes sure the reader is always comfortable with the code.
These small things aside, I think Corey’s video is a great example of TDD in practice! Go watch it.