Every bottle of James Squire Original Amber Ale has a little story about the beer printed on the label. This one is all about how often the original James Squire got laid. I suppose it's fitting: maybe someone will be inspired by label and beer, and use it as an excuse to wake up the next morning and wonder how the hell they got drunk enough for that to look attractive (a question generally shared by the other party). However, its slightly less appropriate to me, having spent this Sunday night in my apartment with a six-pack of the aforementioned, and the X-Box.
Which is an interesting contrast to spending Friday night being rained on in an open-air cinema, watching Grease. I have this theory that every member of my generation (being, as I am, on the fading edge of Generation X, but not quite into the rise of Generation Y) knows this movie off by heart, whether they want to or not.
I didn't join in the singing. Although if I'd had more beer then instead of now, I probably would have.
Anyway, on with the Unit-testing stuff.
I don't write my tests first. I know very few people who do. It's awkward, fragile and unintuitive. For those who enjoy it and find that it's none of those things, great! At best, I'll do a mixture of the two, and have something vaguely functional, then write a testcase and make sure it tests all the conditions I'd like it to pass under even though I know that it'll fail.
I like to write my tests first, often to the point of writing the test, and then using the IDE shortcuts to create the classes and methods I'm testing. Not writing tests first is generally a sign I'm getting lazy or complacent. I find that writing a test first focuses my mind on the precise problem I'm trying to solve, and gives me a nice indication of when I've solved it. In a way, it keeps my honest.
I also like the feeling of certainty. You write something that deliberately doesn't work. You make it work. You are certain that the state of your code has changed. If you write a test that works, change some code and the test still works, have you really done anything?
Worse, if you have some code, and then write a test against it that works, are you sure the test is really testing what you want it to?
I also find that the need for code to be testable colours the way I do design. I'd much rather write code that is easily testable, because then I spend less time writing (and running) tests. Experience has taught me that as soon as you have tests that rely on the container being up to run, you're quite likely to slow down by an order of magnitude. So I try to avoid writing tests that involve a container.
I wouldn't, however, say I do test-driven design. Tests are one of the factors that influence my design, but they certainly aren't some overwhelming force that drives everything else.
Richard Saunders on Unit-testing Tool Boy
Tool Boy (TB) gave me a rant about unit tests saving time. I asked the sorry sod, "if they save so much time then how come you're so late on all of your work?" He talked all about the bugs that the unit tests would find... The truth is that we're not held accountable for that too much. There are always too many parts, so its never clear why the system is unstable... Get your stuff done and shut up about your ficticious unit tests. Time to deployment is job #1, cost is #2, quality is for people not working in IT.
This is what finally convinced me that Saunders is indeed satire. Quality is cost, is time to deployment. I've seen attempts to separate them, and they've all ended in tears.
As requirements complexity increases, test case code becomes a duplicate of the code being tested
This is the big testing danger-sign to watch out for, as I mentioned in a previous rant about mock objects. It's the reason I continue to fight a rear-guard action against the direct testing of private methods. Tests should be stimulus-response. I poke the object this way, it gives me back this result. I poke the object this other way, and the resulting state of the application model is this. Moving in so close that you're testing each individual neural pulse, rather than the aggregate response, leads to tests that are either meaningless, unmaintainable, or both.
Those James Squire bottles irritate me so. James squire didn't start the company that makes James Squire. Mr. Hahn did. Lies! Lies I say!
(today's bitterness brought to you by losing a trivia night by 1 point due to Mr. Hahn and his little stories).
I think that writing tests first is an ideal approach and share your view that it focuses the mind on the problem you are trying to solve. However, I do think that writing the tests second can also be fine, under certain circumstances.
I run an open source project and make use of the amazing code coverage analyser Clover. I had about 4 weeks to write the majority of core functionality with regard to this project and being unsure if I could fit it all in I just went gung-ho on the coding. Along the way I needed to make sure that various bits and pieces were working (bits that wouldn't be used until later down the track, but were the focus of my attention, and thus forefront in my mind then) and I would write some tests. I was sufficiently satisfied if I found that I could get the outputs I expected while having Clover tell me that my tests were covering as much of the code as possible (100% in most cases). While the total test coverage for the entire core is not particularly high at the moment (something like 70%), the main bits are all pretty much coming in @ 100%. This gives me confidence that (assuming I am testing for all the correct things) these bits are doing their job, even though I did not write the tests first.