Saving Time With Jest: Meetup Summary

Originally Posted December 10th 2016

This week I gave a talk at the brand new Triangle ReactJS meetup group on how Jest can save developers time. I was asked afterwards to share the content online for those who missed it. My talk was mostly demos and wasn’t recorded, so there unfortunately isn’t much to share, but I thought I could write out the basic ideas behind the talk, and share them here.

What is Jest

Jest is a JavaScript testing framework built by Facebook to address their internal problems testing JavaScript code. It was open-sourced in 2014, but unlike Facebook’s other recent high profile JavaScript OSS projects like React, Flux, Relay and GraphQL, it failed to develop much traction in the community and mostly stagnated for 2 years. That changed in early 2016 when 2 Facebook developers, Christoph Pojer and Dmitrii Abramov began working on improving the project. Over the past year they’ve brought massive improvements to the developer experience of using Jest.

At a more practical level Jest is a test runner with a built in assertion library and support for code coverage, babel transpilation, and module mocking. It began as a wrapper around Jasmine, an older JavaScript testing library, but has since replaced parts of Jasmine with replacement functionality, while retaining backwards compatibility.

In package.json we have 4 dependencies that are part of a normal React project setup, react, the 2 babel presets for using es2015 syntax, and react-test-renderer, which is a react addon for rendering react for testing, similar to how react-dom renders components for the browser. We then add jest and babel-jest. jest provides the test runner, assertions API, mocking capabilities, and cli. babel-jest is a drop-in dependency that lets Jest integrate with Babel. Neither require any additional configuration in the normal case. Lets say the rest of our project looks like this:

Writing Tests

Jest provides Snapshot Tests, which are a quick way of writing tests to catch changes in the rendered output of a UI component (or any other serializable content). I’ve written about Snapshot testing before, so I won’t go into depth here. But snapshot tests are significantly faster to write than traditional assertion based tests, and for the write type of code can provide greater or equal benefit. This is one area where technically Jest may not save you time. Instead it may take your team to a place where you’re actually willing to write tests for your UI components for the first time.

There are also a great set of codemods for Jest. jest-codemods can help you take your existing suite of tests from Mocha, Ava, or tape and translate it over to Jest automatically. Of course if you were using Jasmine previously, your tests can be migrated without changes. So Jest saves you time by not requiring you to rewrite any tests.

Running Tests

Jest runs tests fast by default. While I’ve seen from comments on my last Jest post and elsewhere that some people may have been able to optimize mocha or AVA to be fast enough that switching to Jest was a downgrade, for most people Jest is going to be faster than whatever they may have been using before. This is true because of performance reasons (tests run in parallel, and mock out timers to avoid unnecessary waiting), but also because of UX decisions. Jest is able to use git and node’s modules system to detect what files have changed since the last commit, and which tests are affected by that. Because of that, it is able to optionally run only the tests that might have changed on each run (jest -o). Since it is usually able to run tests fast as a result (since it only runs a few at a time), Jest also is able to have an awesome watch mode (jest --watch). In watch mode, tests rerun as files change, and there are options to target specific tests, run all tests, or fix snapshots as you go.

Fixing Tests

Jest provides 4 main conveniences for fixing tests

Error messages have clear formatted diffs, making it easy to know the difference between what was received and expected

Error messages have a clear traceback to the line that failed, either the assertion in the test file, or the exception in the source file

Even though tests run in parallel, Jest makes sure that any console output from the test is placed in line with the test output, making it easy to debug with quick console messages

When running Jest multiple times, Jest runs the tests that failed in the previous run prior to other tests, leading to a faster feedback loop even when not using watch mode

More Resources

If you live in the Triangle area (thats Raleigh/Durham, North Carolina to the rest of the world) make sure to check out the Triangle React meetup. The plan as I understand it is to do events once a month, alternating project nights and talks. I believe Tracy is looking for more speakers too, so hit her up if you’re interested. This time 4 of us spoke for 15-20 minutes, so it isn’t as much preparation as other events where you’re the only speaker.