When you’ve been banging the drum for years about the importance of proper unit testing, a strange thing can happen: You can forget why you started banging it in the first place. On those rare occasions when I’m asked why we unit test, I recite a few decades of the Regression Rosary with the necessary reverence, before moving on to the Liturgy of Loose Coupling.
Well I’ve been right back at the coalface for the last few weeks, and it’s reminded me again why I started unit testing and why the only way I’ll ever give it up is when they wrench the green bar out of my dead hands.
The high-level reasons for unit testing are many and well known. They are detailed on websites like www.junit.org. And here is a particularly good way of explaining why unit tests are vital, using ideas from the heady world of bookkeeping.
But what I was reminded of in these past few weeks was how good it feels to use unit tests. This is something that has to be experienced to be truely appreciated. So allow me to share what it is about writing unit tests that I really really love:
I like to know when I’m done.
I can go home. Or get a coffee. Or go to lunch without brooding over a problem. With my regular fix of green bars, I can see that I’m making ground – and that I’m not going to lose that ground to regression errors the next time I make a change. I have distant and unhappy memories of working on code for weeks, knowing only that it compiled, and having to wait a very long time indeed to experience the inevitable ‘oh, you meant…’ moments that big bang integration will always provide. I don’t ever ever want to go back to that feeling of coding in the dark, sure that I’m planting bugs, but never knowing where – until it’s too late.
I like knowing what problem it is I’m trying to solve.
Ever get that feeling of drift? You’ve been coding for ages, but you don’t seem to be getting much closer to the goal. Maybe you’ve been writing code to do the wrong thing. It is so easy to get too caught up in the ‘how’ of a problem that you lose sight of the ‘what’. We’ve all done it, but it’s a lot harder to do when you have tried to code your unit tests before the class being tested. Why? Because the first question you ask yourself – when your fingers are hovering over the keyboard and the empty unit test is open in the editor – is ‘What is the damn thing supposed to be doing anyway’. It’s a great question that sometimes leads to a lot of other questions. And the proliferation of questions can get annoying and frustrating when all you want to do is get on with your application. Until you consider what kind of a mess you’d be in if you were faced with all these annoying questions after the code was written.
Once you’ve been around the Test First block a few times, the familiar feeling – that you don’t know enought about the requirements yet to code them – actually comes as a relief. Whew! I’m glad I didn’t spend a day wandering down that blind alley!
I hate pointless deployments.
When I was in my first year in university (late Jurassic/early Cretaceous) we learned to program using Pascal, and were obliged to use a three-pass compiler. You could hard boil an egg faster than that compiler could deal with a 100 line program, and when we were finally free to start using the phenomenon that was Turbo Pascal, we thought all our troubles were over. But something strange happened – we started to rely on the compiler to catch not only glaring syntax mistakes but even functional errors in our code. Instead of scanning the code to find the source of a problem, we thought “It only takes a few seconds to compile and run – lets just tweak this line here and see what happens“. It was a disaster. We left our brains at the door of the PC lab and succumbed to voodoo coding. We entered into frantic cycles of tweak-compile-run-check, and though compilation time was insignificant, the checking required us to go through all the steps of the running program to get the part that was broken. All this activity made us feel very productive, but it really just made us busy. We were no longer analysing, we were merely tinkering.
Some things never change – every half-decent IDE offers us the same kind of temptation when it lets us deploy quickly – even instantly. It might seem like a real fast way to track down a problem, but the same patterns as described above takes hold. This thrashing behaviour is compounded by the fact that most IDE’s have wrinkles when it comes to redeploying: Did the fix really get deployed? Have I just spend the last hour labouring under some misconception?
Presentation issues and anything involving browser-side processing still need to be eyeballed during a systems test. But most everything else can be unit tested – even Struts actions. I get a satisfying endorphin snack when I find that I can reproduce a system level problem in a unit test. I know that I’ve avoided the deployment frenzy trap, and I may even have found some issues that the requirements overlooked.
How many things are there out there that are both fun and good for you!?
It remains to be seen whether the arrival of JUnit4 has any impact on the fun factor in unit testing.
– brendan lawlor –