I was reading Howard's post today on his crisis of faith with respect to unit testing and it launched an interesting conversation with a colleague. I'm a unit testing advocate. But I'm not a big fan of test-first or test-driven development (TDD). And I'm not a believer in 100% coverage.
I believe that my job is to maximize the value of my time with respect to the product. Of course, how to do that is a big value judgement and one that's likely impossible to actually calculate. I'm generally of the belief that writing tests pays large dividends over time. But writing tests for trivial code (I'm talking about you getters!) is likely not going to pay a big dividend. The time spent writing the test (and maintaining that test) is probably not worth the time.
With respect to TDD, I think the thing that bugs me the most about it is the dogmatism that the only way to build a system is to first write a test. I think that's certainly one way to build a system, but certainly not the only one. I find it to work well to start with tests and API when I understand the concepts in the system well.
But when I don't (which is maybe the more common case), I find it more useful to skip the tests and start with code. Often I will rapidly prototype the skeleton of the system and do several quick rewrites. Usually that's enough to work out the concepts. At that point, I definitely like to start working out the API and writing tests. But before then, it feels like an anchor rather than a safety net.
TDD advocates would tell me to let the tests guide the development of the API and refactor as I go but for me, I just find this annoying and feel that it breaks the flow. But maybe that's just me. I'd be interested to hear what you think.
As Howard mentioned in his blog, there is a lot of value to be had in integration tests as well, and I'm a big fan of having both unit and integration tests to cover the same code base. Or rather, my favorite is to have unit tests, component level tests, and system level integration tests. These three levels weave together to give you a really powerful safety net for your code.