When providing estimates on a project I always include the time needed to write up the tests because they are often necessary to provide a quick turnaround on changing requirements and inevitable bugfixes.
Some managers and customers would prefer software to work as intended from the get-go without tests, but, unless you're developing the simplest of applications, tests are an absolute necessity. Simply telling your customer that "tests are necessary" probably won't do, so here's a list of reasons why they are important that I often employ.
Sure, the format of the files you need to process each night isn't going to change. Until the release is two days away and it turns out the format has changed from CSV to XML. With adequate tests in place, you can replace the file parser and know almost exactly where you stand without having to wait for the application to be tested by a human.
Of course, this does mean you'll have to change the tests for the file parser, but isn't that the easiest way to find out that your parser actually works?
During a project at the Belgian Post Group (now bpost), we used each new version, each change in requirements, of a pretty complex application to add more and more tests. The number of issues to pop up during user acceptance testing went down. Way down. So far down in fact that we had to find other things to do in the days leading up to the release, while a few months earlier we'd still be squashing bugs left and right.
Plus: the testing framework we developed during that project served as a baseline for Unitils, proving that not all testing code you write needs to be redone in your next project.
Code gets ugly
No matter how hard you try to think about the code you're going to write, at some point you'll start to notice duplicate code that can be merged into a single function and weird constructs that can be simplified from 200 lines to 10 lines. Tests have your back and make sure you can merge and simplify without breaking the app.
Imagine a piece of logic -- let's say some kind of calculation based on government regulation -- that's already been tested by the same person five different times. They will get sick of it and they will start to skip the testing. Why? Because it all worked up till now, so why would now be any different? And that's when you come along. You find out the code you've written three weeks ago in part of the calculation is actually the same as the code you've just finished writing. You merge both parts into a single function, but forget about that single tiny special case you needed to take into account.
Boom! Your new report works perfectly, but your calculation is broken. Chances are nobody will find out until it's too late.
Recently, I found out code I had been working on for days failed in some scenarios I hadn't even considered up till then. By the time the first fixes were applied, the code had grown out of control. And then another bug popped up.
I decided to add the newly discovered scenarios to the existing tests and rip out the entire part. I rewrote it to spec (i.e. the tests) in under 4 hours.
Tests are more valuable than comments
When you're the kind of developer who reads the comments detailing what a method does and how it will respond to certain input, you've probably seen your fair part of paradocs: the documentation accompanying the signature says "A" while your experience seems to indicate it's actually "X".
Given clear-cut test cases you'll soon find out whether the original developer (maybe it was you):
- changed the code and forgot to update the docs; or
- wrote buggy code and wrote the docs without verifying the code responded as expected
Tests clarify how you expect your code to be used.
Tests can speed up development
Don't believe me? In a current project we're using JBPM to
embed workflows in a webapp. Using JUnit I can make sure that the implemented
workflow works as expected. This means an email is sent out when expected to the
people I expected. This means the
Send out order step will always occur
Verify payment step. This means I'll always have a quick comeback
to an issue logged by a tester or customer titled
"The workflow doesn't work as expected".
Besides, would you rather compile the entire application, start Tomcat, wait for the application to load and then start clicking away or would you prefer to hit the "Run test" button in your IDE and have the results displayed to you within seconds?
Here's another benefit: the next time your customer asks you whether it would be
possible to add an extra step to the workflow and how much time and money it
will cost, you'll open up your test cases and have a look. Maybe you'll add the
step right away, to see how your tests will react. Imagine, just imagine,
responding to the customer's request with a simple "Done!" instead of a long
winding response detailing why you'll need 10 days to include a
Tests are no magic bullet
Unfortunately, someone still has to make sure your web application works in Internet Explorer 7 and the "Log in" button is visible on an iPad. But that needs to happen less and less, while you add more and more tests.
Just make sure the things you're testing are worth it. When 2 + 2 no longer equals 4, you'll have bigger fish to fry.