Moving from cowboy coding to agile development

Wednesday, February 15, 2006

Another Setback

Once again it seems I won't be coding much on my free time in a long time. My plans suffered a serious setback when I found out that the research group I wanted to join isn't hiring at the moment. So, I guess I have to find someone else who is willing to pay me for doing my master's thesis, or the latter half of the year will be a difficult balancing act between work, studies and writing my thesis. That would not leave time for doing any TDD (unless I start doing some serious propaganda at my current workplace and get to use it here).

Friday, February 10, 2006

On Test Coverage

On Wednesday I spent three hours at Reaktor again, participating in an Agile Finland's coding dojo session for the second time ever. It was fun, and this time I had a particularly good lesson about (lacking) test coverage.

First, a small disclaimer: I don't mean to reprove anyone involved in writing the code that we started with. I can't claim I would have noticed this bug during the previous session myself, if I had happened to be there. I read the code base through before the Wednesday's session and this didn't catch my eye.

Now, to the point. The challenge was to write a poker hand evaluator, and for this, we need a way to construct the hand in some way. This is the corresponding method as it was:


private Card[] createHand(String hand) {
String[] cardStrings = hand.split("-");
List cards = new ArrayList();
for (String cardString : cardStrings) {
cards.add(new Card(cardString.substring(0, 1),
cardString.substring(1, 2)));
}
return cards.toArray(new Card[cards.size()]);
}



This method takes a string representation of a five-card hand, e.g. "DA-D2-D3-D5-D4" (which would be a straight flush from the ace of diamonds to the five of diamonds). The method generates the corresponding Card objects with a suit and a rank. However, there's a small error. A card with a rank of 10 can't be generated, since the latter substring only takes one character to represent rank (and elsewhere in the program the rank was supposed to be "10" - this is also the only card in which the error occurs, since aces are represented as "A":s, and facecards are "J", "Q" and "K", respectively).

The fix was very simple:


...
cards.add(new Card(cardString.substring(0, 1),
cardString.substring(1)));
...

This error had not caught anyone's eye - maybe because there was not a single test including a card with the rank of 10. To me, this raises a question about the right kind of test coverage to use with TDD. Should there have been test cases with every single card tested? Probably not. But this time taking something - even this simple - for granted resulted in a bug.

Personally, I think one of the points of TDD is not to think you have taken everything into account, but knowing you have done so. (Well, of course programs can never be completely bug-free, but you know what I mean...) To a non-expert coder like me, I guess it's exactly the small things like this that I can learn to use extensive unit tests with. Live and learn - sometimes the hard way.