In Response to #NoTDD

Published on

I follow people online who write in a variety of different languages, using a wide variety of platforms. One of the blogs I follow is the MSDN blog. This can be a great source of information of upcoming web standards, or even new platforms Microsoft is trying out. I don’t always agree with everything I read, but I always take the time to reflect on a different viewpoint.

The viewpoint I’ve been reflecting on lately is the #NoTDD article that Eric Gunnerson wrote a few weeks ago. It’s very easy for one to throw up their arms in disagreement with such a bold statement. Let’s instead take a minute to reflect on the points Eric makes.

It takes us longer to write code using TDD

That’s true. There is no denying it. If you have to write tests to cover your controller logic, model, and service classes, it is going to take a lot longer than just writing the classes themselves. This should be fairly obvious. Writing more code takes longer than writing less code. If you didn’t know that by now, time to head back to Laracasts or Code School.

You can’t solve this problem. All you can do is reduce the number of things you are testing. Ignore the 100% test coverage rule. It doesn’t work for well tested frameworks like Laravel. If you are fully testing your controllers, mocking whatever they call, you aren’t testing anything. You’re simply testing that you don’t have a syntax error. A singular integration or acceptance test will find those problems.

The tests get in the way. Because my design does not have low coupling, I end up with tests that also do not have low coupling.

This happens to me all the time. I could have low coupling, but I quite often decide it’s not worth the mental effort. When I need to change things in one class, I usually end up blowing up five others. How is that TDDs fault? In these cases, TDD helps me find the problems in the other classes so I don’t forget something.

If your job involves working on a large enough code base that low coupling is an issue with tests, then you need to rethink the way you have structured your code, not your tests.

Because I don’t have low coupling, I need to use mocks or other tests doubles often.

I agree with this completely. Mocks suck! They are the worst system we have, except for all the others. I hate writing Mocks. I’m constantly thinking about how I would make the class behave like it’s called, without actually being called. It’s a pain that we all share.

I understand the need for them. There is inherit value in testing a class in isolation, outside of any interference from other classes or services. I think that’s why people like writing integration of acceptance tests more. They are easier to write because you don’t have to bother with things like mocks (for the most part).

Design on the fly is a learned skill. If you don’t have the refactoring skills to drive it, it is possible that the design you reach through TDD is going to be worse than if you spent 15 minutes doing up-front design.

Nope. You’re writing your tests with the wrong mindset. Have you ever heard the term “Programming by Wishful Thinking”? The belief is that you write your integration (or in our case tests), that look how you would like your code to look. Then you write the code to implement that integration.

You should be writing your tests with design in mind. Don’t think about how you will implement that function in your service class. Instead think about how you would like your service class to be called. Would you chain in on your object, or call it directly? Would we return the instance to chain again, or simply return the data? Once you decide how this class will behave, you can write the test to call it. Then you can worry about the implementation over and over again, and allow your tests to turn green on a successful refactor.

My Thoughts on TDD

Testing is a tool like any other. You can use it wisely, or go crazy with it. Write your tests so you have enough confidence that when you do refactor, your tests have caught 80% of regression issues. If you’re aiming for 100%, you’re still going to be working on that password reset feature 6 months from now.

Write good tests coverage for the job. If you’re quickly spinning up a shopping cart to sell a few digital products, then write the number of tests that you feel will let you sleep at night. If that’s only 1 or 2 big acceptance tests, that’s fine. On the other hand, if you’re writing software to monitor heart patients, you better be aiming for delivering that 100% test coverage.