Test Driven Development Is Dumb. Fight Me.

A great idea hiding behind a terrible implementation

That’s right, I think Test Driven Development (TDD) is straight up not good. And worse, like a shady Influencer subtly editing out their natural cellulite, it’s giving jr. devs unrealistic goals. So with my tongue firmly in my cheek, let me rant about how writing tests for functions that don’t exist is crazy.

pictured: me wasting time with opinions on the internet

Why do I feel this way?

Namely because I needed something to write about this week, but also because I’ve been talking to Sr. Devs with real experience. Not the ones who didn’t like TDD, but the ones who did. When I asked them about using TDD, they gushed about all the benefits. But when I followed up with, “So, do you do any at work?” I got a very different response.

“Oh uh, well, the thing about TDD is…”

“There’s no time,” “It’s not the culture,” “my pair didn’t want to,” “my girlfriend and I use TDD all the time, you just don’t know her, she goes to a different school.” For something that was so great, there sure didn’t seem to be a lot of people doing it. This was especially frustrating since at bootcamp, I never saw any of my teachers do it, but they all talked about how you should be. Hearing everyone talk about it started giving me a complex, because deep down, I never understood why it was better to do things backwards.

What are the benefits of TDD anyway?

Those who advocate for TDD will concede that it does move slower. But, they claim that the resulting code will be so clean and well thought out, that you will save time in the long run. But what I’ve started to realize is that the reason TDD takes so long is that it’s just…inefficient. This was beautifully demonstrated to me the other day when someone tried to do TDD.

The Incident

I was excited, a Sr. dev was going to show me how it was done. We talked about the feature and our first function to start with, and designed a test and watched it fail. We got started on the function, but after ten minutes or so, they stopped. They noticed that the way we made our function meant that the test would not actually detect it. We had to stop working on our feature to go back and work on the test again.

We started back on our function but felt we didn’t understand how it would interact with the rest of our system. So we started messing with the code to see how it would react. We would change the feature function then log out the results. We saw it would be easier if we modified a config file and made other minor changes, so we quickly made them. It took us a bit, but we finally understood how the feature would interact with the system. It was then that I noticed: 1) our function was fully coded, and 2) the test was wrong. Again.

Why didn’t TDD work?

Because developing software on the job isn’t simple. Sure, when working on toy apps TDD sounds pretty sweet. But in real life, features are way more complex than Function X should take a name and output a greeting with that name . Often times the product request will change mid-work, or you’ll realize that the feature can’t work as requested. Maybe your original understanding was flawed and you have to start over.

All of those situations are normal, but having to stop each time to write a test at the start just makes each problem worse. What’s far easier is writing your code, manually doing some QA tests, and then writing automated tests that mimic those situations, specifically for the code you wrote. With proper tests in place, you can freely move on to the next feature or refactor without being afraid that something will break. By using testing as a guardrail and not a map, you will get all the benefits of tests WITHOUT the issues of trying to anticipate anything.

But TDD does have some good ideas

There is a lot to like about TDD. In fact, literally everything but the tests are great. The idea behind TDD is that you’re able to write a test because you sit down and think about things first. That’s great! Too many developers (me) jump in and start coding without thinking about what they actually need the code to do. Just jotting down goals and requirements for a function will get you all the benefits of TDD without the hassle of literally writing tests.

In Conclusion…

I’m talking about this because tests ARE important. Not having tests on a production app is like driving on a highway without lanes. I’m just saying that TDD is like trying to paint a highway before you pave a highway. And maybe you disagree, maybe you really do use TDD every day and love it. But if you don’t use it, that’s ok too! We have to be honest with ourselves. If a coding style turns out to be great in theory but not practice, let’s keep the parts that work and toss the rest. My convoluted point is: There are lots of ways to code, we need to stop holding any one of them up as the “best” way.

That being said, Behavior Driven Development is flawless and if you’re not doing it, you’re a fool.

kidding,

mike

latest article: How to Build a Dynamic, Controlled Form with React Hooks