September 07, 2020Adèle Gauvrit6 min read
Let me tell you the story of the day I almost quit testing my code altogether. For the tenth times this week, the CI failed with this cryptic error message "Received value does not match stored snapshot" and a diff that looked something like:
<div - className="myClassName" > + className="myNewClassName" > + <div> Hello world + </div> </div>
It felt pointless to fix this test : why does it matter if the class-name is different or I added a div tag? It does not keep me from introducing regressions as nobody in the team reads the snapshots updates.
I was so frustrated, I almost broke the computer, slammed the door to quit my job. But instead, I decided to channel this energy into something more positive. I started thinking about how the project tests got into such a state.
How come everybody agrees that we need to test our code base yet so many developers hate it? Was I the only one being frustrated? (No I was not)
When people say they use TDD, I don’t believe them.— emily freeman (@editingemily) August 26, 2020
Why is nobody doing something about this?
Here is my theory to make sense of this kind of situation. I have called it "The vicious circle of testing" ™:
If this resonates with you, you've been writing tests for the CI to work but not for your teammates to understand your intent. Tests are a collaboration tool, they are meant to be read when they fail by you of your teammates. You need to make sure you can understand them in a month when you have forgotten all about what you were supposed to do.
Tests are meant to be read by humans, not your CI.
How do you write tests for humans, you ask? Here are my 3 tips for you :
Writing great tests for humans takes time, you need to be invested in what you are doing. You cannot be if you do not know exactly why you need to write great tests.
Do not write tests because you have to. Make sure you and your team know why you write tests.
Automatic testing is often a given when setting up quality tools for your project. Unlike your linter, tests do not fail every day, they are a longer-term investment to code quality. It is easy to lose sight of why you are doing it.
Before starting to set up your test environment you should clarify why you are testing.
What are you hoping to gain in the long term? Better documentation? Fewer regressions bugs? Developer experience tool for TDD?
Make sure you and your team know why you are doing it. Because it is so easy to fall into the vicious circle of bad testing, if you all know why you are driven to write tests, you can catch early when you are deviating from your goal. Making your goal clear will give your teammates ownership over your test and they will help you push for improvements when needed.
If we chose to use snapshots on my project, it was to go faster. We wanted to test all of the codebase without investing much time. By aiming to keep a 100% coverage, we started writing tests that needed to be maintained every time we added features. They could not help us catch regressions because they changed too often. No matter how small the investment was, it was not worth it.
Do not aim for a 100% code-coverage of generic tests, aim for 100% of readable tests
You do not need to test everything. Your set up may not be adapted to every aspect of your code.
I always write unit tests for very logical functions :
But for most part of the code, it is a case-by-case study.
Should I test my frontend app UX? If I am writing a complex single-page app, UX is very likely to evolve. Testing it may be my priority so I can prevent regressions that have a big impact on the user's appreciation of my app. I want to write integration or end-to-end tests for this.
Should I test your frontend app UI? If I am writing a shared-component library, I am focusing on UI and have a few logical components. My first mission is to provide my users with reliable and consistent UI. Testing UX logic is a bonus, it is ok to make choices and not to focus on this at first.
There are a lot of great testing tools available. Now that you know why you want to write tests and what parts of code you want to focus on, you can find the tools that fit your needs like a glove
On another project, I chose to test my frontend React app with react-testing-library. I wanted a tool that :
That is why I chose react-testing-library to write integrations tests on it. It turned out to be a great developer experience. I also had a personal goal of trying this new tool that had a lot of great reviews.
Find a tool that makes writing test fun, or that makes you want to do test-driven-development, you will only write tests for humans this way.
Now you know: if you ever find yourself thinking testing is useless or painful to maintain, you are probably in a very vicious circle of testing. If you want to escape this, here are the steps to follow:
Web Developer at Theodo