The (Some) Fallacies of Test First Development
Written on November 5, 2009 – 7:06 pm | by admin
I should first clarify that I would never come out against the idea of writing tests for your code. I find testing to be a wonderful way to aid refactoring, fight regression, and build developmental confidence in a piece of software. Lately I have tried to provide significant test coverage for projects I work on. My problem is with buzz word fanatics, suits, zealous developers, and tangentially related technical staff who question myself or my team in our decision to not require test first methods as part of our normal development procedure.
Fallacy #1: Test first development is proper unit testing.
Unit testing serves two primary purposes. It allows you to have a fast and efficient way to verify that code you have written is working properly and it provides a mechanism to guard against regression. Bugs that are found are easier to keep fixed and business requirements are easier to maintain as a project ages and grows. There is nothing in either of these purposes that dictate when a test should be written. If anything writing tests after you have your implementation in place fits just as well if not better with these two goals.
Fallacy #2: Test first development will improve your work flow and make it easier for you to focus on the task at hand, providing you with a more efficient and effective coding session.
I tend to write my code more like Bob Ross will paint a portrait. I know what I want to end up with and I have a palette of the tools I need to get there. I would love to say that I always have a proof of concept and that write-one-to-throw-away is the only way to go but the reality of deadlines and business requirements means that this is not always possible. When I sit down to code I am not sure that method 'a' is going to return 'x' and method 'b' is going to return 'y'. All I know is that I have a large module that needs to do something and I have an idea how to get it there. In order to get there I need to put some code on the page and work with it and modern languages afford me that luxury. We are long past the era of punch cards and 2 am university time shares with one chance to get your code correct. Writing unit tests at this point is potentially a waste of time because I have not yet decided how all of the units fit together. You can argue that I should know these items or that I should use my tests to figure it out before I start coding but I write software because I enjoy it and the act of development is a creative and evolving process. Testing first has shown itself (to me) to be detrimental to this part of the process. For me it causes hyper focus on trivial components and interrupts my thought process when an implementation change causes major test refactoring. Test first also causes me to write tests for features that do not make it in to the final implementation because I thought I might need them when I started. I can see where forcing test first may help inexperienced or junior level developers but I do not think it should be considered a process requirement. In the end a good, experienced coder should decide what works best for them. In this case I choose general regression focused testing over test first development.
Fallacy #3: You should always shoot for 100% code coverage and this is a good reason to test first because you won't write any untested code.
We should be smarter than this. A good developer should be able to decide which areas of the code are likely to be fragile and what should be heavily tested. In fact, by definition, 100% coverage does not actually mean what it seems to imply. 100% coverage only means that a test suite encounters every line of code in your application. It should be obvious that this is a pretty useless metric. If an editor reads every line of a novel does that mean that the editor made sure all of the i's were dotted? So what we really want is 100% functionality coverage and this means that you are at the mercy of how far ahead of the process you can think, how many edge cases you can imagine and what bugs you have seen in the past. Unless you are willing to spend a considerable amount of time dreaming up things to test you will not likely be anywhere near 100% of "useful" coverage. I'd further argue that striving for 100% coverage (by its definition) is a waste of time. I find that the 100% coverage mentality tends to lead to insignificant and even useless tests so using it as an argument for test first development is tenuous at best.
Fallacy #4: If you are having a hard time writing tests first than you are not doing it right.
I am not going to even justify this overtly arrogant statement with an extended argument. The fact of the matter is that the "right" way to do test first may not work with a person's development flow, style, or approach to coding. If their personal approach to writing code provides solid and relatively error free code with a useful test suite than who are you to tell them they are doing it wrong?
The bottom line is that "when the tests get written" is a matter of personal preference. An intelligent and experienced coder should decide for himself what works for the given requirements. At no point should a business requirement dictate that all programmers write their tests first. Sometimes I write my tests first and sometimes I write them last, I do not suffer from delusions of grandeur but I am a good programmer and the answer to "when do I write my tests?" does not change that. So write your tests first, second, third or parallel if that works for you and stop giving me the gas face every time I state that I do not always do things your way.