A recent podcast of Joel "On Software" Spolsky and Jeff "Stackoverflow" Atwood stirred up a bit of a debate. Joel goes into a big rant against Unit Tests and the SOLID design principles. Robert "Uncle Bob" C. Martin, author of both the SOLID design stuff and also professional TDD zealot already responded, attacking the points Joel made.
First of all, I do understand the point Joel and Jeff are trying to make. Both unit testing and architecture can be over-emphasized and that will do more harm than good. Like everything else, solutions sold in black and white are usually some shade of gray in the real world. However, to get the point across, you sometimes tell things a bit more simple and extreme.
Joel should be sensitive to this, as most of his articles, including the Joel Test, are structured exactly the same. Unfortunately, Joel seemed to lose patience when hearing about things like test everything and decouple everything. In the talk they use weird examples that have very little to do with the original ideas behind the concepts. I hear these so called Straw Man arguments (proving a point by using a wildly exaggerated example) quite often regarding testing and design. but I was just as shocked as Uncle Bob to hear them from someone like Joel Spolsky, who can be considered a very public software development figure.
Basically the argument against unit testing and SOLID made is: "it's too much extra work". Joel goes on and on about how many millions of interfaces he would need and that all of his thousands tests break when he makes a single change. Of course these are wild examples that have very little to do with the real world, but what I am really missing is: what do you have to do instead, when not doing tests and abstractions? Joel only evaluates the costs of unit testing and proper architecture, but not the benefits.
Not doing unit tests will save you the time to write and maintain unit tests. However, unit tests have a certain goal (to validate if a single piece of code works). If you no longer write unit tests, how will you achieve this goal? A manual test will likely take at least 10 minutes (fire up the modified system, navigate to the proper user interface, enter some data, evaluate response). Writing a single unit test, on average, takes the same amount of time. However, in the debug/retry cycle, unit tests really start winning out. Afterward, unit tests can be recycled over and over, to immediately detect when a code change causes something to break.
With these productivity increases and risk mitigation, I can understand why someone would like as much unit testing as possible. Unit tests are great for testing what a developer can reason about and only involve the isolated unit. Unfortunately, there are more problem classes in a system, such as "is this user interface pretty", or "if I put X and Y together, will they work together". Code that deals with these kinds of problems may be impossible to unit test, or doing so would be extremely verbose and non intuitive. I would agree that it would be more efficient to skip unit testing for this kind of code, and test these attributes using other forms of testing instead.
At the end Jeff closes with a Frank Zappa quote: "Nobody gives a crap if we're great musicians.", concluding that users really don't care about code quality. Somehow, this part seems to suggest that if you care about unit testing and proper design, you can't care about anything else. That strikes me as a bit narrow-minded: it's not like testing and caring for user needs are mutually exclusive? Also, even Frank Zappa probably would have checked the sound before a performance, and look into the mirror before he went on stage. Because Frank Zappa knows the quality of his mustache matters, and not looking in the mirror is not an option.