Why I've Stopped Writing Snapshots Tests in Jest
And why I think you should stop too
I'm developing a frontend application for quite a while now, and my team and I have a strict standard regarding unittesting out features - every new feature must be thoroughly tested with unit tests (Jest + Enzyme for our client, which I'll be talking about in this article).
It took us a while to find the right path for us, all while learning how to use the tools we've chosen to the full extent, but through trial and error we've found a paradigm that works for us.
One of the first things you learn when reading Jest
's documentation is how to write Snapshot Tests. They are meant to be the ultimate testing utility, and they interact beautifully with React
components. You can "render" a component in your test under some condition, save it to a snapshot, and if in any future test the output of the component changes the test will fail and tell you that you've changed something you probably shouldn't have, and if you did it on purpose, you simply update the snapshot to reflect the new state of the component. For the purpose of this article I will explain the snapshot process briefly, but this is not an educational article - I strongly recommend the documentation of Jest
for that.
In practice, it goes something like this - let's create a super simple component that look something like this:
A simple test for it might be something along the lines of:
When we first run the test, it passes and creates a new snapshot. The snapshot looks like that:
Not too complicated as it is a super simple component I wrote in 2 minutes.
Let's say time passes and the component changes. It now looks like this:
My component obviously changed (I'm the one who changed it). Running the test now would result in a failed test, as the snapshots don't match, so I'm forced to update the snapshot to reflect the new state - basically forcing my test to pass.
Now that we have a basic understanding of snapshot testing I can make some bold claims as to why I have stopped using them entirely, and why I think you should too.
- It's really hard to be specific as to what your test is actually testing. You can get away with that writing very small tests and have very descriptive names, but at that time I feel like a designated test for a specific use-case would be clearer, easier to maintain over changing demands and less fragile to irrelevant changes in your component.
- Constant updating of snapshots can create an "if-it-doesn't-pass-just-update-it" attitude, especially when there are dozens of snapshots failing at once, and you/your teammate might be too lazy to actually task a closer look at each and every one of the failing tests, so updating them all becomes nearly automatic.
- They provide no helpful information as to how the code is used, and how it should behave. They merely show what is rendered in a given situation, without any concrete assertions to help future you/new developers understand why or how the magic of your components happens.
This is my personal opinion on the subject, I'd love to hear different opinions about snapshot testing (not only in jest). Do you still write them? Have you found some enlightenment that I haven't? Please share!
Top comments (7)
I couldn't agree more.
The thing with snapshots is that they are indeed useful to detect the impact of your UI changes across your components. The problem is that we overuse this to the point where we stop doing actual assertions and only do snapshots, which break every time anything changes and definitely put you into the "just update" mindset.
For now, I'm certainly moving towards more descriptive and precise assertions other than snapshotting everything. We certainly should be writing more tests following the
@testing-library/react
approach and doing more assertions withjest-dom
matchers. This leads to more readable tests and less false alarms in your test suits.Finally someone said it, and I am not feeling like the only one who thinks like this. I have no big experience in writing tests for react, but I wanted to learn it, and wrote a few snapshot tests and I got the same conclusion. I simply dont see the point of snapshot testing, because, if component is changed that probably means that I changed it for a reason, and I would regenerate all the snapshots, anyway.
The only thing that makes me think that this testing makes sense is if for example you update react itself or some other libraries that are maybe generating components. So they render components differently. But then again, I would probably just update snapshots. 🤔
Yes exactly. Plus updating a snapshot solved all the problems in the test - what if there are 2 faults? A regular test would contain 2
expect
s that will fail independently, and fixing one might not be enough.i must say that you brought up some good points in your post however i think that this is kinda looking at snapshots testing without any context. i'll try to explain what i mean regarding the 3 claims you mentioned:
"It's really hard to be specific as to what your test is actually testing"
i think this is relevant to any test methods/tools that you choose to work with - when you write a test one of your major issues is to make sure that someone else who reads your test will understand exactly what you are testing (giving a good "describe" and "it" titles helps, but there are other ways too). if you do not do that then with no doubt the test is bad.
writing good tests takes time... there are no shortcuts.
"Constant updating of snapshots can create an "if-it-doesn't-pass-just-update-it" attitude"
oh wow, this statement is bad. like really really really bad.
this is pretty much saying that when you write a code you have no responsibility what so ever to what you write and that you don't try to understand the implications of changes you made in the code. maybe i'm a bit harsh but if i find someone in my organisation who behaves like that then either he does not understand what snapshots are made for or he should be fired...
"They provide no helpful information as to how the code is used"
now THAT is something i can def relate to. indeed snapshots have little information regarding the code. this is why snapshots are very bad when it comes to test the functionality behaviour of the components (as apposed to just rendering) - that should be done using specific tests and not snapshots.
the big strength of snapshot comes in testing render result of the component with different props. when it comes to rendering they give you a 'good enough' direction as to what changed and from there it's usually pretty easy to find the prob in the code.
to sum things up, i think that jest snapshot is a powerfull tool, and with great power comes great responsibility. use it wisely and it will serve you well. abuse it and it will come back at ya...
Never tested with snapshots, avoid test recording. Basically you identified what I find wrong with the optimize for fixing tests mantality.
The expectation that you can just update your tests when an expected change happens allowing for tests to surface unexpected changes, ignores the behavior of the human mind. Evaluation of the test needing to change will dwindle especially when easy to update.
Edit: This does not mean do the same thing and make it hard to update.
I think snapshot testing adds no value to the project.
They are just a burden. Enzyme is a much better option to invest in.
Amen! I agree with everything you've said. I think the most important point you have was about large, complex, stateful components - if you got there you should reconsider the component altogether.