The Order of Tests
It’s been awhile since I’ve done much coding. That’s not my day job anymore, and I lose interest working by myself. In the past week, however, I’ve had a couple opportunities to mob program remotely with the Canton Coders. With the COVID-19 restrictions on gathering in person, people are much more likely to work with you virtually.
So last week I found myself mobbing on the Roman Numeral kata and today on the Zeckendorf kata, both on cyber-dojo. A lot of fun was had by all, and I rediscovered what I know about Test Driven Development with a bit more clarity.
Both of these katas involve converting base-10 numbers to some other representation. It’s a natural assumption to start with 1 and work your way upwards. This can make your work harder than it needs to be.
It becomes even harder if you start with an error condition. Looking for the Roman numeral equivalent of a
null did not help us move the code in the right direction. Handle the happy path first, to get the code designed for its utility, and then add the error conditions that make sense. We quickly decided it made more sense to use an integer parameter, which couldn’t be null, anyway.
Beyond that, ordering the test cases in numerical sequence of the calling parameter will ask you to take some bigger steps than is necessary. Bigger steps provide bigger windows for errors, and reduce your flow.
In the Roman Numeral kata, starting with inputs 1, 2, and 3 is OK. For 1, the simplest path to a green bar is to “
return 1.” The 2 case begs for an “
if” statement. The 3 strongly suggests refactoring to avoid a long list of “
if” statements. So far, so good.
The 4 case, however, takes a big leap. It introduces a new output symbol, “V,” and a new concept, out-of-order symbols to represent subtraction. That’s a lot to do all at once.
We skipped that for a moment, and did 5 and 6, first. The case of 6 develops the need to consume one character and then work on the next. Then we went back to 4. I think that was premature. We hadn’t yet developed looping on any symbol other than “I,” so generalizing that and using a table of symbols didn’t come naturally. In retrospect, I think it would be wiser to do 1, 2, 3, 5, 6, 10, 20 to advance the looping over one symbol to more than the “I” symbol. We might want to check things with something like 28, but that would drive the algorithm further. I’d rather continue with 4, 9, 14 to introduce the subtractive characteristic.
The key is to think about the next smallest step in developing the algorithm rather than the next smallest step in the input. Of course, if you get it wrong, things are not lost. It just takes a little longer.
Very good points, George. Especially focusing on the next smallest step for the algorithm vs the input.
All of our “steps” should be evaluated with the lens of “what gets me to green the quickest”.
Thanks for the posted retro and reflection! Indeed, a great time was had by all, but it’s always nice to reflect on how we might be better next time.
Generally good points, but I think that it is a conceptual mistake to consider IV to be 5 – 1. Yes it looks like that, but conceptually, IV is s single symbol. IV, IX, etc. are different types of symbols than I, V and X, because you shouldn’t concatenate I to them. I think good testing points to start for Roman Numerals is 1, 5, 10. These are really simple cases that don’t require any postfix concatenation. Then 2, and 3, which requires multiple concatenations of I. Then 8, which requires knowing that you need to switch from base concatenation of I to V. Then 20 followed by 27. If that all passes then you have the basic pattern in place. Then handle 4 and 9. No subtraction is necessary if you treat IV, IX, etc. as symbols, instead of as an I prefix to V or X. Anyway, those are the order of tests I use and it simplifies the math.
Oh, another reason I try to keep the testing and algorithm progression as simple as possible is that I had one team of senior devs that I was coaching get way too to in the weeds in their own approach (which was heavier math) and they lost sight of the point of the kata was to learn TDD. My less experienced teams took baby steps and were more coachable in TDD and mobbing. It is hard to unroll a rat hole, if an team new to TDD goes too far down the hole.
Good points, Camille. I think you’re right about thinking of IV and IX as symbols, rather than 2 digits with a relationship between them. I seem to recall coming to that conclusion years ago, but didn’t think of that when we were working in increasing order of the decimal numbers.
Another sequence that occurs to me is 1, 3, 10, 30, 22, 5, 38, 4, 9, 34, 29… or something along those lines.
George, Pretty good sequence.