The first 2 hours of TDD are the most painful
Quick Background
I admit, I’ve had a lot of failures with TDD. Mostly they were solo projects and I didn’t have the discipline and self control enough to stick with it. I ALWAYS regretted not sticking with it. However poorly I was doing it, it always gave SOME value and saved me from several bugs (earning its keep and paying back with dividends all the time I spent on it). And the successes with TDD I have had have been rocky, at best. I usually felt ashamed and embarrassed by this, seeing how there’s all these noted luminaries and successful practitioners on my Blog Roll talking about optimizing, tweaking and even redefining the style of TDD as BDD.
In my selfish desire to find out their secret, I worked with Ray Houston to try to trick a bunch of really good software developers (many of whom already had lots of TDD experience) to see if I could get them to teach me their secret ways so that I might become more proficient and successful at TDD. I didn’t expect it to work very well. BOY WAS I WRONG.
I was kind of down on the CodingDojo in my last post on the subject. I was bummed because some people came from great distances and left with less than I had hoped they would. I was bummed that I didn’t serve them better. But, there were some really great things that came out of it. It did spurn a bunch of people to get more serious about what they were doing and take a second look at how they were doing it. But more importantly, it re-instilled confidence in people (including me) who had been wavering and unsure of where to go or how to do TDD more effectively.
It was truly great to see people whom I thought had TDD down cold, experience some of the same problems I have been having and not have a quick answer for it. This reminded me the most important thing about TDD…
TDD is not a solved problem, yet.
You cannot minor in TDD at college. Heck, you cannot take a graduate level course on TDD at college. TDD is not a fully solved problem. It’s a practice which has been proven, through experience of many, to be a useful, worthwhile, and valuable tactic for achieving higher quality, more agility (through change confidence), and measured, disciplined design.
Armed with this reassurance that I wasn’t totally a heel, I really started to get into the discussions, the debates, and, above all, the code at the Dojo. I started jotting down some of the questions that were being raised and not answered all that great in the hopes that I could spend some time thinking about them.
I plan on writing more about these things as the weeks/months go on (especially when I start on with Jeremy and get to practice them more thoroughly and have more substance to write about). But in the mean time, I thought I’d do a thought dump and see if anyone had any good rules of thumb, concrete advice, or even ‘laws’ to go by. I’ll be updating this post with any interesting comments that appear so that you don’t have to go hunting through them to find any gems (of course, all the comments are gems — except for Anonymous Blog Coward ones — but some are worth bringing to the top).
(P.S.- I’m trying to keep the BDD style questions out of here, that will probably be another post)
TDD Practice Questions
- How much up-front design do you tolerate? How do you know when to stop (i.e. ‘when algorithms start getting discussed, it’s testing time’)?
- What about certain “I just know we’ll need this” type stuff (i.e. putting a try/catch{Console.WriteLine(ex);} in your console main() method?)
- When writing a test, in order to even get it to compile, you have to build an interface or two, a concrete class with some NotImplementedExceptions in it, etc. How far do you allow that to go?
- If, during the middle of testing on a story, you realize that your up-front design wasn’t correct, do you stop and discuss with your pair right then, do what you need to do and proceed, or do you pull back and go back to full pre-test design mode on that story?
- When proceeding to a new story, you discover that a test you wrote for a previous story no longer reflects the requirements. Do you refactor that test immediately, mark it as ignored until you finish the current story and cycle back to the ignored one? Something else?
- If the new story’s requirements involve a slight tweaking to an existing test, do you tweak it, or make a new one and discard the old one (i.e. ‘No changing existing tests!’ or ‘Only change if it’s a minor compiler issue, but otherwise don’t change it’)?
- If you’re, say, building up your model and it passes tests, but you’re seeing that it’s infantile and that the next few upcoming stories will produce significant changes to produce a new emergent model, is it appropriate to step back and consider a larger refactoring, or do you keep plugging and make the changes into the existing model even if it could benefit from some housekeeping that is otherwise out of scope?
TDD Style Questions
- Assert.That(x, Is.EqualTo(y)) or Assert.AreEqual(y,x)?
- How many asserts/test? Any caveats?
- How do you know what to put in the SetUp method?
TDD Mechanics Questions
- Is a refactoring tool absolutely necessary?
- If so, what is the bare minimum features that the tool would need to facilitate decent TDD?
- Integrated IDE test runner or a background source-watching auto-runner?
That’s most of what I wrote down with a few extra thrown in for good. I’d love to hear some of your thoughts on these questions.