Over the weekend, I noticed this tweet appear in my timeline:
I write tests following TDD when it makes sense00:28 AM - 27 Jun 2020
A bunch of people replied to this tweet asking: Great! But... when does TDD make sense?
Especially on the front-end, this question comes up a whole lot. Front-end programming has a legacy of being unsuited for TDD.
With that in mind, here’s a simple set of guidelines that I use to help answer this question.
If... | Then... |
---|---|
You’re unsure if TDD makes sense | Use TDD if you can (see below for why) |
You’re working on a team | Use TDD |
You’re writing static pages without behavior, like a marketing site | Don’t use TDD |
Getting to market fast is more important than quality or maintainability | Don’t use TDD |
You’re unsure of what you’re building | Spike first, then test later |
You’re working alone on an unreleased project | Don’t use TDD |
You’re working alone on a released project with users | Use TDD |
Interested in why I arrived at these conclusions? Read on.
You’re unsure if TDD makes sense
With enough experience of TDD, you will understand when to apply TDD and when not.
So if you need to ask the question “When does TDD make sense?”, then TDD makes sense.
You need more experience. You need to get more practice.
Practice doesn’t necessarily mean building toy programs. Instead, find opportunities in your daily work to try TDD.
Finding ways to shoe horn TDD into your daily work practice is a whole topic itself, so, for now, I’ll suggest just this:
Start small. Next time you’ve got to add a new component to your React app, try doing it with TDD.
If you’re working on a team
TDD is a structure that helps you articulate and outwardly express ideas that would otherwise be locked in your head.
That makes it a great socializing tool for getting feedback early on your designs.
TDD goes hand-in-hand with pair programming (when you work with someone else) and team programming (sometimes called mob programming, which is when an entire team works together in front of one screen and one keyboard).
TDD can also give a speed boost to teams.
Ever experienced how slow the code review process can be?
You wait patiently for feedback and then, when it arrives, you context switch back to make the suggested changes. Then you repeat the cycle. This takes a whole lot of time and it’s mentally (and emotionally!) draining.
When you apply TDD with others, you pull that feedback process forward, which saves time later on.
If you’re writing static pages without behavior, like a marketing site
TDD is about testing behavior. Your marketing site does not have behavior.
Sure, you might want to add acceptance tests for this code, but that’s a different part of your development process.
If getting to market fast is more important than quality or maintainability
If you think following TDD will slow you down, and that in turn will lose you money and market share, then don’t use TDD. You can always come back to add tests later.
If you’re unsure of what you’re building
To “spike” is to write code without tests. Often you do this when you’re exploring a new technical domain for the first time. Spike until the point that you’re confident of the shape of your code. Then you can start adding tests.
You’re working alone on an unreleased project
If you’re building a side project that doesn’t have any users yet, and may not ever have any, then I’d avoid using TDD unless you’re specifically aiming to get better at TDD.
This can be argued two ways. On one hand you could say that TDD will delay finishing, and that translates into a risk that you will never finish.
On the other hand, you could say that without TDD you’ll end up with low quality software that risks never attaining any users because of the poor quality.
Of course, there are other ways to have a poor quality product other than simply having buggy software. You could build the wrong thing entirely: in other words, something that no one wants to use.
So for me at least, the scales tip in favor of not using TDD. Instead, you should focus on getting a finished first version ready.
However if you’re absolutely sure that your project will one day have users, and the use cases and requirements are clear, then start with TDD. It’ll save you time later on.
You’re working alone on a released project with users
The moment your side project starts attracting users, then you want to start using TDD in order to save yourself from nasty regressions.
I’d love to hear feedback if you agree, disagree, or if this was in any way useful. Go ahead and leave a comment below.
Happy coding! 🙏
Top comments (9)
Thanks for the write up, it seems balanced and well thought out.
I'm a big proponent of TDD but I'd suggest adding one case to the Don't use TDD set. When you're learning a new technology/framework. I've previously made my life harder by trying to fit my ideas of how to write tests based on previous experience onto a new Technology only to find that once I understood the technology then I could understand the testing paradigms that went with that technology.
That’s already covered under “If you’re unsure of what you’re building”.
But in general for frameworks I would make sure you’re at least wrapping them in abstractions so you’re not completely coupled to them.
Also a very important point.
Thanks for bringing this up. This is probably worthy of a blog post on its own as there are at least a couple of related considerations:
Good article!
So if you need to ask the question “When does TDD make sense?”, then TDD makes sense. I think this sentence is great !...
I disagree with this one If getting to market fast is more important than quality or maintainability, in my opinion, TDD and tests, in general, should be added in your project from day one, sure it will take a bit more time to "deliver features", but at the end, the curve of delivering will be constant and if you resign quality the curve will grow exponentially and you will be delivering things late or even with a lot of bugs and hacks...
It’s a good point. Not using TDD risks slowing you down, especially if you’re working alone and rushing, without being careful. That’s when you end up with bugs, for sure.
They're all valid points to an extent. A single developer can follow TDD even if their team does not, but a single developer a team does not make. To effectively adopt TDD, your team should adopt it together, not just an individual here, and an individual there. We want people to be creative, but we don't necessarily want developers following their own ideals in development if it's contrary to the way the team, or department works.
TDD requires a certain amount of knowledge and fixed scope ahead of time. On some projects this is achievable, on a lot of projects where time and budget is a constraint, it's just not practical. It has strengths and weaknesses, such as providing a blueprint for your application and known logic ahead of time. That in itself is also a weakness, because it has a dependency on requirements not changing frequently.
Indeed, you could pick any arbitrary work and write a failing test for it, so that you know what the design is going to be ahead of time. But if for some reason, you're no longer able to fulfill your TDD contract, you have a failing test - that may even end up in the primary code base.
As for the example of developing an application based on docs, and not being able to guarantee the completeness and correctness until production, that's just insane.
I'm not against TDD, I just don't agree that you can, or should, use TDD in every scenario listed above, because a lot of people don't know how to use it.
TDD relies on strong practices by BAs, QAs and the developers. TDD is more pie-in-the-sky, far more often unobtainable without strong culture, an adherence to the method, and time to set it up.
In order to make TDD work, you will need to know ahead of time:
TDD can be done in an agile environment, but it relies on tests existing before development, which means an expert level knowledge of the domain at that point in time.
TDD is the unicorn, an impractical style of coding, borne from a time when waterfall was king.
Here is my point of view devz.life/blog/test-behaviour-not-...