Why and how TDD works for me
The most important things I learned through my own mistakes.
It’s hard as a beginner
Let me start with something completely different.
In my late 30s, I started going for regular runs.
And it was really hard. I wanted to run three kilometres because the paths around my village offered themselves for it. But I couldn’t! I’m not totally unathletic, but I spent a lot in front of a computer in the last decades (maybe you know what I mean).
There’s this voice in my head on the first two kilometres that said: “Why are you doing this? This is hard! Why don’t you stop right now and go back home? You don’t have to run! You don’t have to do this!”
You know what — the mind is really stronger than the body! I kept on running (slowly and with infrequent walking breaks), but even though I thought, I’ll never enjoy this. Never!
Three years later, I’m playing hobby soccer nearly every week and often go for runs in between or when there aren’t enough players for a match.
Last week, I hit my goal of 5 minutes per kilometre in a 4K race in Vienna.
And I enjoy it!
It took a long time and I often had to conquer my weaker self.
I have a feeling it’s similar with TDD.
In the beginning (of any project) nobody writes good code. You code, and you’re so focused on finding a solution. Nobody will succeed on their first attempt. The mess will get worse if you don’t go back regularly and clean up your code. TDD can help with that a lot.
Red — Green — Refactor
For any of you unfamiliar with TDD, it works with this cycle:
You need the refactoring step to write good code. And you can only change code without fear (and with confidence) if you know everything still works (aka is covered by a test).
Who of you doesn’t know that feeling when you look at code without tests:
you know if you touch it, you break it. And if you touch it, it becomes yours. So you try not to touch it (or not too much) and walk away and leave the mess as is. You’ll never be able to change this into good code.
I still remember when it clicked for me with TDD. I felt so empowered!
I finally had the confidence to change the code into the shape I had in mind after reasoning about it.
That’s why TDD works for me.
What’s a unit?
Back then, I made the first mistake. Even though I had read some books and articles on the topic, I had the understanding, that a unit is a single method or a class. A unit had to be small. That’s how all the tutorial videos on YouTube work. Of course, they have some rather simple examples.
A unit (or SUT — system under test) most of the time should not be that small!
Because what happens if the unit is that small? You couple your test to your implementation! And that’s a very, very bad thing for you as a developer. Ever had the case when after a change, suddenly dozens of tests went red? Hopefully you make this mistake only once (like I did).
There are two schools of thought regarding TDD, but in my opinion, both are on the same page when it comes to coupling. Always think about the size of your units!
More about that in the videos linked below.
BDD and TDD
The second thing was when I discovered the other DD — the behaviour driven development (BDD). I threw myself into Gherkin and wrote all the business requirements as readable tests. You know what? I now think that’s most of the time a waste of time. I still have to meet a client which really works with those tests and can think that logically to understand how they work (yes, they are written in “plain English” but at the same time they are not. The phrases need a certain structure, which not always feels that natural at all). People don’t need to think logically for a thriving business.
And then I discovered that others are struggling with this too, and already thought about it much longer than I had the chance.
You can write your unit tests with behaviour in mind! That’s when I started TDD on the Command and Query level (these are terms of the CQRS or hexagonal architecture) and I understood that I had to redefine what a unit meant for me and my tests (see above).
Enlightenment
I show you three important videos on my journey to my current understanding of TDD here (I wish I had known about them sooner or had a mentor to help me with this.).
You should really take the time to watch these!
The first one is “TDD, Where Did It All Go Wrong” by Ian Cooper:
next is “Effective Unit Testing” by Eliotte Rusty Harold:
and last but not least “Improving your Test Driven Development in 45 minutes” by Jakub Nabrdalik:
Conclusion
I’m still far from perfect using TDD (especially when working on legacy code), but with endurance and the infrequent “walking breaks” I’m on the right track.
You need to practice a lot and take your time, and stay open for new perspectives and ideas (as with everything in our job). And you can’t afford to stop learning!
Tell me about your journey (and your struggles) with TDD/BDD in the comments.