Confession: I Quit Relgious Unit Testing
I used to be very devout in the ways of Unit Testing and Test Driven Development, even proselytizing to other developers. But for a few years now, I've been apostate. I just haven't found them to be that useful in my projects anymore, mostly because I end up having to throw them away after a year.
I've used religion-oriented language in this post because there has grown a very religion-like following around TDD. To preach otherwise is to speak heresies that we cannot permit to be heard, lest our children hear it and start having ideas that they, too, may ignore the gods of their elders.
The problem is that Unit Testing can only exercise known behavior. For new systems, behavior is frequently unknown. When it does become known, it often only makes sense in the context of the system. And frequently, it’s also likely to change dramatically in the future. Unit Tests written in such a scenario are often nothing more than API exercising.
They can validate that the code provides an answer, but they don’t validate that the code provides a correct answer. You can’t write a unit test to predict how a database migration will impact the production database. You can’t write a unit test to see if the layout of the text on a variety of screens is comfortably readable. A unit test can tell you if you calculated the mean, median, and standard deviation of a list of numbers correctly, but no unit test that you write will tell you if that information is useful.
One of the key features of Unit Testing—the help they provide in avoiding regression during code changes—specifically inhibits the rapid change that is necessary in greenfield projects. Unit tests are rigid to your API and rigid to your results. If your results have to change, your unit tests are now just wrong. And if your API has to change to suitably calculate the new results, then your entire suite of tests has just become obsolete.
In such a situation, a unit test suite is nothing more than a saved REPL session. That might be a desirable thing. REPLs are great for exploratory programming. But that’s all it is and you have to be prepared to understand and accept it in this reduced capacity. Don’t let your large unit test suite distract you from making the decision to change your program interfaces, if the change is truly necessary.
Unit Testing is useful for standards-based software development as the standard provides the results to which comparison can be made. But for line-of-business applications, Unit Testing should be considered a code smell, a signal to search out where this solution has already been implemented.