How to make your sluggish Jest tests go faster

Vitaly Kondratiev
ITNEXT
Published in
3 min readFeb 8, 2019

--

Photo (slightly amended) by Michelle Yorke

Make unit tests great again

Jest v23 was released in May 2018 and the headline of this release was “Blazing Fast Delightful Testing”.

However, at the beginning of 2019, it feels like the motto should have been “Utterly Sluggish Repulsive Testing”. Here’s why.

I recently decided to improve unit test performance on a newly joined project. It felt like it takes too long to test the whole suite (32 tests only) as well as test a separate file in isolation with watch mode. The direct consequences of that are that developers are not enjoying the process and trying to avoid touching unit tests. Product quality suffers in the long run.

Challenge accepted! I started investigating what can potentially go wrong.

Here’s our original project’s setup:

  • React v16.5
  • Typescript v3.1
  • Jest v23.6 using jsdom as testEnvironment
  • ts-jest
  • Win10

npx --envinfo --preset jest

System:
OS: Windows 10
CPU: (4) x64 Intel(R) Xeon(R) CPU E5–2698 v3 @ 2.30GHz
Binaries:
Node: 8.11.1
npm: 5.6.0

To cut the long story short, please find below a list of steps to speed up your tests at least 2x.

Jest v23 has performance issues

When running in watch mode it takes an enormous amount of time for Jest to update, it’s easier to restart tests altogether.

It turns out that a regression has been introduced after version 22.4.4 that is not yet fixed and causes a significant slowdown.

Step 1
Downgrade Jest npm install jest@22.4.4 --save-dev

JSDOM environment is slower than Node

JSDOM is a JavaScript implementation of the WHATWG DOM and HTML standards. In other words, jsdom simulates a browser’s environment without running anything but plain JS. It runs tests fast but not as fast as pure Node. The difference can be two-fold.

Create react app users saw the regression in performance with CRA v2 upgrade that in turn brought along jest v23.

Step 2
”testEnvironment”: “node” can be set as default for your tests, it will even allow to shallow render and test React components.

// package.json"jest": {
"testEnvironment": "node"
}

On those occasions when using DOM is required (e.g. mount a component), you can simply opt-in a spec to use another test environment by adding a comment on the very top of the *.spec.js file:

/**
* @jest-environment jsdom
*/
import React from 'react';

Parallel testing is not always good

While Jest may be fast on modern multi-core computers with fast IOs, it may be slow on certain setups.

Step 3
As prescribed by Jest, one way to mitigate this issue and improve the speed by up to 50% is to run tests sequentially.

npm test --runInBand

Another alternative is to set the max worker pool to ~4. Specifically, on Travis-CI (free plan machines have only 2 CPU cores), this can reduce test execution time in half.

npm test --maxWorkers=4

Experiment with these flags and see what works best for you locally and in CI environment. Set up separate tasks for the various environment if required.

I hope that the steps above will help to revive your unit testing and make it a bit more delightful. Let me know in the comments what was the improvement like in figures and what worked for you.

UPD: Jest v24 was released recently, hope to see improvements to some of the issues above.

This post was originally published on my company’s blog. Our mission at Appfocused is to help companies execute great user experiences on the web by utilising our vast experience, knowledge of the modern UI trends, best practices, and code craftsmanship.

--

--

Independent Tech Lead specialising on executing complex business-critical User Interfaces on the web platform. https://www.appfocused.com