Why I am switching to test-driven development
I am going to change the way I code.
My working pattern is, roughly, as follows:
- Sketch a basic method implementation
- Test it manually
- Fine tune the code, improve implementation
- Further manual testing, fix a few bugs
- Write a test
- Done! Make a cup of coffee.
Is there anything so bad about this process? I write a test, so I get one gold-star. And there’s nothing wrong with the end results: I write good code, which usually works. But I think I could work better. Every time I’ve written a model or controller for as long as I can remember, a little voice in my head asks: “Why haven’t you written the test first…?”
Anybody else get the same little voice? I suspect there’s a few of you out there.
The more I’ve learnt about TDD, the more I’ve wanted to practice it. At first, it just seemed like a way of ensuring thorough test coverage, but that is actually just a sweet, sweet bonus. For me, TDD is more about changing my entire mindset when it comes to coding. The benefits promise to run deeper than may first appear obvious.
Sure, testing first will remind me to focus on what I want my code to do, before I start coding. This is valuable, yes - and I can see it helping me avoid a few refactoring/start-from-scratch sessions when my brain hasn’t quite been in gear - but I don’t believe that it will much improve my resulting finished code, so much as make the process of getting there a more efficient.
The more precious benefit, is that the pre-written tests will tell me exactly when to stop - and that’s a time when it’s a lot easier to trip up. Especially a day later, or a month later. The habit of testing first will prompt me to keep my methods small and manageable. Small and manageable in the short-term, equates to easy-to-maintain and stable in the long-term. A method of working which virtually obliges me to create manageable, bug-free code? And as good as guarantees a working stack of tests across my application?
There’s a whole host of other good reasons too, some of which I am perhaps yet to fully appreciate, but enough already. I am convinced.
So, why aren’t I doing it? My only problem is discipline. That’s going to change.
Test-unit Zappa
How will I switch to TDD? Firstly, I will drop Test::Unit and make the switch to RSpec.
Why switch? After all, the Test::Unit framework is a proven system in itself. It’s been shown to be more than capable of providing in-depth test coverage in complex applications, and is also usable within a strictly test-driven environment. What’s more, it’s true to say that there’s little testing that can be done with RSpec, that can’t already be done, one way or the other, using Test::Unit.
Isn’t switching from a system I am already well familiar with, simply going to be a short-term hindance - and offer questionable benefits in the long-term?
There are two stand-out reasons. Firstly, working with a different testing framework will force me to throw out my old habits, and hopefully help me to break my old routines and shake up my testing in the way that I want. Old habits die hard, and sometimes need a little persuasion.
Secondly - and perhaps even more importantly - it’s about changing the the language in which I write tests. RSpec’s descriptive idioms - typically written as something.should_have - are forward-looking, and cry out to be written and defined before the method they test. This is quite different to Test::Unit, which really encourages working the other way around.
As Josh Stephenson highlights here:
Just as sociologists have postulated that the language we use to express the world around us directly affects the way we interpret it, the language we use to test applications directly affects the way we develop them.
So RSpec will force me to throw out both my testing routines, and my vocabulary. I can’t do much more to create a catalyst for change.
Of course, I will be monitoring my work-flow, productivity and the resulting code carefully. If, after a reasonable period it is clear to me that TDD is not working - back I can go. But a decent spell of practicing TDD, a good level of familiarity - a fair test, so to speak - is going to be needed before I can conquer that little voice in my head, one way or the other.
In due course, I will post my progress here.
References/Further reading
http://www.agiledata.org/essays/tdd.html
May 11th, 2008 at 8:55 am
Go for it!
I don’t necessarily write tests first, but I am writing tests very closely with changes. I find also that the TDD approach supports the design of nice contracts, as you’re thinking about how to use your API as well, so method names tend to end up more user-friendly as well (I’m not afraid of 200+ char methods if it is the shortest way of concisely describing what the method does).
It also helps make it clear what the methods actually do. I know of a bunch of methods in a certain code base
that … well it’s taking me a long time to figure exactly what they do and what tests to write for them.