A couple weeks ago, I met up Attila Domokos and did the LCD rubyquiz. Let me set the scene about the pattern in use at these Hackabous:
-
Pair up.
-
One test is written first.
-
Only as much functionality as is needed to make the test pass is written.
-
The next test is written…
…and so forth.
We moved through parsing the command-line easily, then coded the test for displaying a single digit. We noticed we were at a particular sort of impasse:
Implementing as little code as possible to pass this test could not produce code which could survive the next test. At least, not in a way that I can see.
What should you do? Should you write the code, debug it and pass the test, then add the next test and delete the code? This seems like an odd question to ask. The only reason I even ask it now is I’ve found some people who really advocate this.
Another example: I listened during the Roman Numerals kata as one team made first I, then II and III pass by coding:
def convert(n)
n.split("").size
end
If I understand proponents' arguments, in writing the code you are learning, and this learning will dominate the inefficiencies in this process over time.
I honestly think this is a misreading of agile. Agile was built in the context of an industry addicted to wasteful, heavy and rigid process. Should TDD become a wasteful, heavy and rigid process?
How do I proceed in these cases? First, I have nothing against writing more than one test up front. If I can think of several of the corner cases and potential pitfalls right now, I will write them down in xUnit. Sometimes switching from researching the requirements to coding is an expensive operation, and in these cases, I’ll lay out five or ten tests documenting the requirements. Sometimes, I have no idea how I’m going to implement something. Writing a batch of tests up front allows me to explore the corner cases and think more about designing a useful approach.
Given the multiple tests, I have no problem writing the more complicated algorithm first. We’ve already determined that we can’t (or perhaps just don’t know how) to evolve it, so we’re going to end up going for it anyway.