Take a picture, it will last longer

Demystifying snapshot testing in Javascript with Jest.

Brad Dunn
4 min readOct 24, 2017

At 4Thought Studios, we use javascript extensively on our early-stage project Epochly. Our project is built using the React Native project maintained by Facebook’s engineering team. Naturally, we also took a look at their offering for testing in javascript called Jest. Jest is a wonderful product, and is truly standing on the shoulders of those testing frameworks that came before them, grabbing all the best techniques and offerings from previous frameworks and reintroducing them into a single, streamlined and extremely performant packages. Tests- when written properly- are fast fast fast. I could go on for quite some time as to why Jest is a pleasure to use, but plenty has been written before on this subject. Instead, I want to focus on one aspect of Jest — its concept of ‘snapshot testing’ and why this simple addition to the testing framework really makes writing effective tests in javascript so much easier.

I’m going to cheat a little bit in this article. I’m not going to teach you how to use snapshot testing in Jest as plenty of great articles already exist on this subject as well. Event, the documentation for Jest, does a good job of explaining how to use them effectively. My goal instead is to communicate why snapshots are useful — something that took me longer to understand than I’m comfortable admitting. Let’s dive right into the TL;DR.

Arrange, Act, and Assert

Right now, when we want to test a component, we generally speaking follow the arrange, act & assert flow of writing tests. We set up our isolated environment to simulate a particular state of our application so that we can be certain that our codebase behaves predictably given our pre-defined arrangement. We then run the parts of our codebase that will give us a result to test. We then assert that these results were what we expected. Simple enough right?

// Function to test
// Borrowed from Jest Docs -https://facebook.github.io/jest/docs/en/getting-started.html#content
function sum(a, b) {
return a + b;
}
// The test itself
test('adds 1 + 2 to equal 3', () => {
// Arrange
const a = 1;
const b = 2;
const expected = 3;
// Act
const actual = sum(a, b);
// Assert
expect(expected).toBe(actual);
});

Keen eyes may call foul at this point and say that you can simplify this test drastically without losing legibility. This is true, but my point is that we still go about the three steps of arranging, acting, and finally asserting.

For a simple example like this, we aren’t doing a ton of work to set up and test our codebase, but what if we have a more complicated result to test? What if we want to test that our function constructs and returns a complicated JSON tree? Suddenly, we are duplicating the work that our function is doing by dropping a bunch of formatted JSON into our tests.

What if business requirements change to add a new field to the required JSON output of our function? Now we have to change both our function and our test to match the new formatting requirements of our JSON. At the end of the day, we are writing the same code twice just to ensure that our tests pass. Seems like a bit of a waste…

Time waste… Wasting time… got it? Ayuk yuk…

Simplify with Snapshots

At the end of the day, we care about whether or not our codebase responds in a consistent way given consistent inputs. We construct the expected output solely so that we can check to make sure it is identical to the actual output of our function.

Instead of keeping everything in sync manually, let’s just have Jest do the hard work for us. Let’s have Jest take a ‘snapshot’ of our function’s output and we can just spot-check this output to see if it’s what we expected the function to do. Anytime we need to change our code, Jest will compare the snapshot (the expected result) to the actual result of the function. If they don’t match Jest tells us “Hey — take a look! It’s not the same anymore!” If we intended the snapshot to change, great! Let’s just tell Jest to update. If not, then we’ve just caught a regression in our codebase!

// Function to test
// Borrowed from Jest Docs -https://facebook.github.io/jest/docs/en/getting-started.html#content
function sum(a, b) {
return a + b;
}
// The test itself
test('adds 1 + 2 to equal 3', () => {
// Arrange
const a = 1;
const b = 2;
// Assert
expect(sum(a,b)).toMatchSnapshot(); // Much nicer!
});
// The snapshot file
exports[`adds 1+ 2 to equal 3 1`] = 3;

Save yourself some time and headache — let Jest snap a few pics of your codebase and sleep easier while writing your tests.

Further Reading:

--

--