What is wrong with TDD

My first big issue with TDD is that it tells you to write tests first. How are we supposed to write a test for code that does not exist? The answer is that you cannot effectively test code that has not been written yet. You end up writing your code to satisfy your tests rather than writing code to build your product or accomplish your goal.

Let’s use an example. We want a function that takes in an integer, which represents a percentage grade that a student has received and tells us what letter grade that would equate to. Here is an example in C#:

This is a simple example with some obvious bugs. We can see what the requirement is in the function’s summary and we can see how the code does not satisfy the requirements.

It is obvious that if the grade were 90, for example, our function would return ‘F’. This does not satisfy the requirements and it should be clear to any developer that we just have to add in some “or equal” signs and probably throw an exception when the grade does fall into one of these categories it’ll be good to go.

Back to the main point, the question is, did we need to write a test for this code before we wrote it? I don’t think we did as there would have been no value add to do it at that step.

To explain more let’s take a look at what the tests might look like:

These are just 2 test cases, but you can gather what the other ones might look like (exactly like these ones). So what would be the purpose of making this before we wrote the code? I suppose a better question is would this have added any value by writing this test first? Some would say that it adds value because then you would have caught the fact that your code would have failed.

I argue that the tests would have a similar value whether you added it before you wrote your code or after your entire codebase is complete. The reason I make this argument is that this would not have changed the fact that a test would have caught this problem at any stage in development (preferably before pushing it to prod).

I made sure to bold the word similar because I actually think adding your tests after your code is complete adds more value than adding your tests before the code is complete. I also believe that it is egregious to add a full test suite to test code that doesn’t exist.

I think of it this way because any time we write code we are trying to solve a problem or reach a goal. All the code we write should be written in order to solve that problem or reach that goal NOT in order to satisfy some test cases. I think of it like trying to proof-read a paper before it’s written.

As developers, it seems as though we are constantly trying to push more code faster. Come out with better features, refine the features that exist, do it faster. I think that following the process of TDD will largely hinder the rapid development of features and ultimately stop you from being as innovative as you can be. When you write tests before code it can be so easy to lose sight of what you’re trying to build and the goals you’re trying to accomplish. This will lead you to create features and code that really misses the mark in many respects. Too often I have seen people re-write sections of code, not to make the code better, but because it will be a little easier to test. At this point, we are taking away a lot of the value of that code because it is no longer written to solve the problem it is written to test.

Another problem I have is that TDD takes away from a lot of common sense. In my simple example, I don’t even think tests would have been necessary. I think that a good developer would have been able to look at the requirements given and use their power of common sense to pick out the bugs. In every environment, I’ve seen TDD used as a way to combat common sense as opposed to empower it. When we write tests for such trivial pieces of code we’re really just wasting our time and trying to make ourselves feel better about the code. We tend to use this process as a crutch to lean on so we don’t have to use some really basic common sense.

Lastly, TDD does not stop bugs from being shipped to production. If you make software it’s going to have bugs no matter what you do. I don’t think TDD necessarily promises that you will never have bugs, but I think a lot of project managers tend to think of it in that way. Let’s be very honest, nothing is going to stop you from having bugs in your code, it will happen now and it will continue to happen until the end of time and TDD won’t solve that.