Fixing Jest Memory Usage on CircleCI

If you're running out of memory or your tests are hanging when you run Jest tests on CircleCI, try running jest —maxWorkers=2 instead of just jest.

Why?

On my current project, we're using Jest and Enzyme to create unit tests which we run as a step in our CircleCI build process. Every time a PR is opened on GitHub, CircleCI rebuilds the project, runs the tests, and lets us know if that PR's code is stable.

About 400 tests in, however, an issue emerged — all tests would pass locally, but the CircleCI build would fail. The CircleCI logs made it clear, though, that no tests were explicitly failing. Something was making the build hang at the test step, it would time out, and the box would consider that build failed.

We realized that the issue might lie with how Jest spawns child processes. Although test output appears linear, the tests by default run in parallel, using up to as many workers as there are cores on the machine. Maybe Jest was spinning off the wrong number of workers and this was causing memory problems on our CI box.

The first thing I tried was running jest —runInBand, which makes Jest run all tests in the same process (more info on Jest CLI options). This turned out not to play well with things that need a headless DOM rendered via JSDOM. We use Aphrodite for styling, and runInBand seemed to prevent this DOM from being rendered, which meant Aphrodite couldn't find any elements to attach itself to.

Next, I tried jest —maxWorkers=1, but this seems to do the same thing as runInBand, and I got the same result. —maxWorkers=2, however, let the JSDOM render and all the tests run. I put this change in our Circle config file and the subsequent PR was the first one that built properly in over a week.


Since then, our CircleCI builds have been stable. Tests take about 46 seconds to run on our CI box now, compared to 9 seconds locally, where we don't need to limit workers.

Thanks for reading this far! Now go out there, write tests, and integrate without fear.