How to learn TDD
How can you learn Test Driven Development? The question seems trivial. What is the difference between learning TDD or learning anything else in programming? In my opinion, learning TDD is similar to learning software architecture or domain-driven design. It is not like learning how to use a library or the standard library and the syntax of a new programming language.
What does it mean to “learn TDD?”
First, we must decide what does “learnt TDD” means. When are we finished? Have we learned TDD if we had implemented only one test? Have we learned TDD if we had copy-pasted some code from the Internet? Like software architecture or DDD, learning TDD requires living with the consequences of your decisions, reflecting on them, thinking about how to improve the tests, and fixing past mistakes.
Everyone can write a test. Not everyone can write a test that helps to implement the software faster. No one can do it on the first try. Mistakes and getting stuck are a part of learning.
Learning TDD is not a one-time event. It is similar to learning cooking or learning a foreign language. You are satisfied with the results. But, one day, you learn about something new, and it changes everything. Your skill raises to a new level. You wonder how you could be satisfied with mediocrity. Of course, the “mediocrity” wasn’t bad a minute ago. It is a “mediocrity” now when you have a new point of reference. A week ago, it was the best thing you could do. Learning TDD is similar.
How to learn TDD
The only way to learn TDD is to practice it every day. It is going to be painful. You will stumble upon problems, and you won’t have any idea how to deal with them. You won’t have time to solve all of them. I suggest picking one issue, the most trivial one, and focusing on it until it is no longer a problem.
Did you over-mock your code, and now you can’t do any refactoring? Focus on testing larger chunks of code and mocking only external dependencies. Do your tests randomly pass or fail? Focus on making the code more deterministic. Do one thing at a time. You won’t learn it overnight.
At first, it will slow you down. The people who are complaining about TDD stop at this stage. They have no idea how to write tests. It slows them down, so it doesn’t work. BS. If you do it twice a year, it will slow you down. But it happens due to a lack of skills, not because there is something wrong with the technique.
Programmers are weird. On the one hand, we talk about “imposter syndrome” (which, in some cases, is our way to “humble” brag about the things we achieved). On the other hand, when we can’t master something in a few hours, we claim it must be something wrong with that thing. You won’t master TDD in one day. It won’t happen in one year, even if you do it every day. Seeing the mistakes you have made and fixing them is a vital part of learning. You need time to make those mistakes. You need time to look again at your “brilliant idea” and realize you were wrong. You need time to learn how to fix those problems. You need time to be wrong again.
Attention. I’m going to say something controversial. You can’t do pair programming with a more experienced developer and learn TDD this way. Sure, they will teach you their best practices. They will tell you what to do. But they won’t show you what didn’t work and why it was a bad idea. Learning from other people’s mistakes seems reasonable until you realize you have no clue why they made those mistakes. Such a deep understanding is possible only when you are the one who was wrong.
Do you preach getting out of your comfort zone? Learning TDD will take you so deep in the discomfort zone you won’t even know the name of the problem you have. Good luck googling that. I firmly believe this is the only way to learn it. Every shortcut you take will make you think that you do redundant work. You have to see what happens when you don’t do it or write them in the wrong way. “Seeing is believing” is very much true in the case of TDD. First, you have to experience the problem to appreciate the solution truly.
It is too difficult!
You have to choose your problem. You can choose manual testing, hope-driven development, and weekends with bug fixing. Is this the easy way? Seriously? I think it is the way leading to burnout.
You can choose the discomfort of TDD. You can choose having no idea what you are doing and whether you are doing it well. You can choose re-learning how to write tests over and over again until the day when it no longer slows you down. Until the day, it becomes the natural way to code. Until the day when you can say, “if it passes all tests, I deploy it in production,” even on Friday afternoon.
It won’t get easy. Never. I constantly make mistakes and realize I do TDD wrongly. However, the “wrong way” right now is much better than the hope-driven development years ago.
You are scaring people off!
Perhaps. But I want to be honest. I don’t want you to be disillusioned. A person who has never been running in their life wouldn’t try to run a marathon. In this case, you would start with more realistic expectations, like running for 10 minutes without stopping and then increasing the distance or speeding up. You would slowly build the capability of running a marathon. Programmers expect to master a new technique in a week. It is not going to happen. Instead, I can promise you a few weeks of pain. It will be as uncomfortable as training for a marathon if you have never been running before.
If you are any similar to me, you will hurt yourself while running. When I see progress, I try to push myself and do more. This is when an injury happens. At this point, we can stop, or we can adjust the technique and continue. Similarly, you will make a huge mistake in TDD and wonder whether you should stop doing it. There will be a bug in production. The proponents of TDD promised it wouldn’t happen! They had lied to you! TDD doesn’t work! Does it? Does one bug mean that the technique doesn’t work? Or do you need to improve your skill?
How do I start?
To start learning TDD, you have to start doing it. Open the code editor and write the first test. It will be weird. It will take a lot of time. Most likely, it will be useless. You will probably over-mock the dependencies and make it impossible to refactor the code. Do it. Then do it again. Then check whether you see any problems and look for a solution. Repeat. Keep repeating.
When you get stuck for the first time, look at the J.B. Rainsberger article based on Kent Beck’s tweet. It will help you take another step forward.
It is the same as starting jogging. Just go and run. If running for 200 meters is enough to be out of breath and it makes you think you will die, the running technique doesn’t matter yet. Also, looking for the perfect running shoes doesn’t make sense yet. Don’t bother installing a fitness tracking app; there is nothing to track yet. You don’t even need to take water with you; you will be back home in 5 minutes anyway.
Learning by doing is the only way, but you have to start doing first.
Did you enjoy reading this article?
Would you like to learn more about software craft in data engineering and MLOps?
Subscribe to the newsletter or add this blog to your RSS reader (does anyone still use them?) to get a notification when I publish a new essay!
You may also like