I’ve just completed today’s 12 TDDs of Christmas and realised that I haven’t blogged about my experiences on days four through to today (day six). Perhaps the reasons for that will come out as I write this blog post. The code, as always, is at https://bitbucket.org/CraigHawker/12-tdds-of-christmas/.
It’s fair to say that I’m enjoying some elements of this and not others. I’m still finding it hard to approach something like Monty Hall in a way that makes sense to test from a “black box” perspective. For example, for Monty Hall, should which doors are chosen even be visible to the calling entity? If they shouldn’t then, arguably, all that should be public is a method marked public bool DidIWin(bool useSwitchStrategy). So we’re then down the road of creating proxies or objects that inherit from the Monty Hall object(s) just to expose bits to testing which I know is something people argue about a lot. Also, how do you write tests for something that’s supposed to be random (which door’s chosen by the user and which door’s opened by the host)? Suffice to say that I’m going to re-visit Monty Hall and re-write it, probably from the ground up, with a much better TDD approach. I’m chalking this down to the learning process and what I was trying to concentrate on (TDD) over what I wanted to achieve (the actual code).
Day five’s challenge (FizzBuzz) was much more testable but I found the challenge almost the complete opposite to the Monty Hall. This is code with a finite set of inputs (integers between 1 and 100) and an algorithm that borders on the obscenely simple. In fact, all I did was throw test data into an array and iterate over every single possible integer in the range and test it was correct.
Day six – Recently-Used List – has been much more useful for me. It lacks the uncertainty and hidden complexity of the Monty Hall challenge but had a bit more to bite off than the FizzBuzz one. I found that this challenge was the one where I’ve started to actually approach the code from a “proper” TDD approach; by only implementing exactly what’s required in order to make each specific test go green, then adding layers of complexity as and when I write tests for each one. I actually quite enjoyed this one and extended the task slightly (only slightly) by making use of generics within .NET to allow the recently-used list to be used with any type rather than just strings. That did make me alter the specification slightly by treating nulls and empty strings separately but that’s because from a .NET perspective they are.
What’s also nice is that I got some positive feedback from @martin_evans last night regarding my approach to the Number Names challenge. I’ve since realised there’s a few more tests that need to be added as there’re situations where commas and “and”s may not be 100% correct.
But that’s the point of this, right?
Items in this series:
- 12 TDDs of Christmas (day one: Calc Stats)
- 12 TDDs of Christmas (day two: Number Names)
- 12 TDDs of Christmas (day three: Mine Field)
- 12 TDDs of Christmas (day four: Monty Hall, day five: FizzBuzz and day six: Recently-Used List)
- 12 TDDs of Christmas (day seven: Template Engine)
- 12 TDDs of Christmas (day eight: ranges)


Re: testing randomness, A good way to do this would be to run the game a number of times and check that the results fall into an expected range. For example, we know that always switching doors should result in roughly a 66.6% success rate, so your test could check that the actual success rate is close to this.
The way this kata is worded makes this one more tricky than it should be. Instead of just creating and testing a monty hall game simulator, we are to create a program that tells us the success rates of various strategies of the game. It feels counterintuitive to create tests that test for those success rates since we aren’t supposed to know them. But really, we do. So IMO its ok to test them.
January 2, 2013 @ 11:08 pm
I agree re: the fact you shouldn’t be able to create tests for the success rates because you’re not supposed to know them. And, the problem with anything random, is that even with reasonably large iterations there’s still a chance when the tests are run it may fall outside of the expected range. The chances are slimmer the larger number of iterations you run, but they’re non-zero.
As I said, I think I’m going to re-work this kata/challenge once I’ve completed the other ones. I’m still not 100% sure on what the best approach is and it appears that a lot of other people are still a few katas behind me so I can’t even have a look at their approaches
January 3, 2013 @ 6:56 am