- Nate Geslin
Speed Up Jest Tests By Using The Correct Environment
The DOM is expensive. Use it only when you need it.
Recently at, Parallax, we noticed our UI test suite was taking longer and longer to finish. This was on the order of minutes, so not a major problem. At least not yet. It was a problem affecting development, though, and lengthening the feedback cycle. This was something we wanted to address sooner rather than later.
We decided to investigate and see if we could speed things up.
As of this writing, our UI app has right around 1,600 unit tests. We use Jest TypeScript and React Testing Library. About half of our tests are for React components that need a DOM. The other half are pure functions or TypeScript classes. These don’t need a DOM to test, only a node environment.
Jest runs via CLI using Node. Things like
document, and the like don’t exist in Node. So, we have to provide a fake DOM to Node. As you can imagine, tests that need a DOM have that added dependency of some sort of DOM library.
Jest documentation of Jest testing calls out jsdom as the recommended tool for this job. You can set the Jest environment in two ways; globally via Jest configuration, or by using a special doc block within individual test files.
I should mention, in our configuration, the default global environment was set as
Any guesses on how we made things better? I’ve already dropped some hints. I’ll give you a minute to think about it.
From a high level, our solution was to set the default Jest environment to
node. Then, within tests that needed a DOM, we added a docblock to tell Jest to use the
jsdom environment instead of
I’d like to acknowledge that we didn’t just figure this out on our own. Like any good engineer, we found the answer on the interwebs first.
To put this fix to work in our project, we did it in three easy steps:
node As Default Test Environment
This had an immediate positive impact on speed. But also resulted in half of our tests failing. We expected this because, well, node doesn’t have a DOM. So the tests that needed a DOM were all now a little grumpy.
Add jsdom Docblock To Component Test Files
Once we moved to
node as the default test environment, we suddenly had a collection of failing tests. Our directory structure made it pretty easy to find most of the component tests. Once a component test was located, it was a matter of adding a doc block with the correct environment to the top of the file.
/** * @jest-environment jsdom */
Then we re-run the tests and verify things are passing again. Easy-peasy!
Update Component Generators To Include jsdom Docblock
The last step is just as important: update our generators to include the docblock. That way new component tests are created with the correct docblock.
How much of a difference did this actually make? Our tests do run faster now. This makes sense, considering we spin up a DOM only when we need it (about half the time).
After we made this change, we went from about 120 seconds per run down to about 80 seconds. Not a massive change, but one that did make a difference.