|laziness, impatience, and hubris|
Re^4: testing codeby adrianh (Chancellor)
|on May 06, 2004 at 09:30 UTC||Need Help??|
I agree with the sentiment, if applied to testing in general, but I don't see how it furthers the argument for testing first.
If I had to summarise it I would say that:
Say you've got a problem that will need about 1000LOC to solve.
When I'm writing test-first I'm developing code in tiny increments. First a test to indicate something that my code doesn't do. Then just enough code to make that test pass. Then refactor out duplication. Repeat until done. If a test fails I know it has to do with the very small piece of code (usually only a dozen or so lines) that I have just written. The majority of bugs are caught very early.
With test last you write your 1000 lines, then write the tests. You'll get multiple test failures indicating that there are bugs somewhere in your 1000 lines. Tracking them down is harder because they're not related to something you 'just did'.
If you're like me the second thing you'll discover when writing the tests last is that some of your code is hard to test. There will be code that's hard to 'get at' with a simple test case and you'll either have to go refactor the code a bit, write a really complex test case, or just ignore the whole issue.
When you look at the cases that are hard to test you'll be saying to yourself things like "Hmm... that's happening because Foo is too tightly coupled to Bar. If I separate things out a bit I can test Foo and Bar separately".
Writing test-first forces me to write code that is testable by its very nature. I'm writing the test first then writing code to make it pass. In my experience this tends to force your code towards good things like loose-coupling naturally, and gives you pretty darn excellent code coverage as a side effect.
For me this last issue is probably one of the biggest gains test-first has given me. By forcing me to deal with API issues, coupling, etc. up-front it helps drive the code design in the right direction. For me test-first and continual refactoring produces better code more easily than other approaches I have tried.
As an Aside: If you're wondering the reason why testing is not a big priority at this job, it's because the perl is almost all demos and one offs. If it's not worth saving, it's not worth testing (much) in my mind. So mainly I seem to be testing the code that gets re-used. As that code grows, so do the tests.
For me the distinction is whether it actually needs to work or not, rather than whether its going to be reused :-)
Tests are obviously really useful when you reuse code as change detectors. If you break some code the tests will fail and you'll know you have made a boo-boo.
Fairly obviously tests are also useful to see whether the code does what you think it does. When you write test-last hopefully most of these will pass since, while you've been developing, you've been running your code with ad-hoc examples and doing some debugging when it doesn't do what you expect.
What test-first does in my experience is make that development time faster because you spend less time debugging. You spend less time finding what's wrong with your code because you're writing in small increments and testing each increment as you go. Because the tests you've already written act as change detectors you also get immediate feedback if you accidentally break something you'd already got working.
Because of this saving in debugging time I find test-first worthwhile even with code that's only going to be used the once.