To be more precise the title should have been "The case against enforcing Test Driven Development (TDD) as a strength jacket onto developers". I have absolutely nothing against people using TDD if it helps them write better code. The problem I have is with forcing developers to think and behave in a way that it's not natural to them. Those who want to use it fine, the ones that don't let them be.
So you're against unit tests?
Let's start by distinguishing TDD from Unit Tests because TDD cops usually equate not using TDD with not using unit tests. A unit test is a software/code which validates a separate individual unit of code. In other words a unit test answers the question "Does that piece of code does what it's supposed to do?". Test driven development is the process of writing the unit test before you write the actual unit of code, you then run the test and verify that it fails, create the unit of code, run the test and see that it succeeds, and finally refactor the code if necessary.
When I receive code from someone, or when I write it myself, I want the following 3 things (in order of importance):
- Working code
- Unit tests which verify the code works
- Comments to explain 4 things: what the class/method does, inputs, outputs, and exceptions.
As long as you give me those 3 things I'm happy and I really don't care which one you do first.
How did we get here?
In the days of yore we created code, and we quickly found out when we revisited the code 6 months down the road it was difficult to know what it did. Then we created comments to remind us of what we have coded. And life was good.
Then a genius (a consultant no doubt) came up with the idea of Comment Driven Development (CDD), the process of writing your comments before writing the code. They saw it was good for them so naturally it must be good for everyone. And life became miserable for people who liked to write comments after writing the code. This is because as you write your code you tend to refactor, introduce new classes/methods, etc. this becomes painful when you have to write/rewrite your comments every time you introduce/remove new elements to your code.
At some point we created unit tests to make sure our code did what it is supposed to do. And life was good.
Then a genius (a consultant no doubt) came up with the idea of test driven development (TDD), the process of writing your unit tests before writing the code. They saw it was good for them so naturally it must be good for everyone...
But how will you know that what your code needs to do?
This is another thing TDD cops and other process oriented people tend to get it wrong. Unless you're doing exploratory code or something similar, when you sit down to write code you do know the results you want out of it. Granted, it may be the wrong results because you didn't do your homework to make sure your goals are aligned with the business, but using TDD does not solve that problem it just makes you follow a process.
So you start (I hope) with a list of things you have to accomplish with your code which are aligned with the business goals. The first item says "Do Something", in TDD you start by creating the test for the method DoSomething. The problem is that while you're doing it you find out you're better off refactoring, creating another class/method/function, or implementing a pattern. But before you do that, you have to create the test for the new unit of code. The end result is that, like with comment driven development, you end up wasting time creating tests for functions that will probably get refactored as the code matures.
Can you have your cake and eat too?
I have to say that Context Specification Development as explained by Scott Bellware on Herding Code episode 42 (great podcast by the way) is definitely a major improvement over TDD because it really is concerned about testing the *what* of the application. The initial unit tests are there to make sure the program does what it's supposed to do (hint: provide value to the business).