简体   繁体   中英

Jest - Simple tests are slow

I am using Jest to test an angular app and it is taking a really long time for simple tests to run and I can not seem to figure out why.

My Jest setup in package.json :

"jest": {
  "modulePaths": [
    "<rootDir>/src",
    "<rootDir>/node_modules"
  ],
  "testPathIgnorePatterns": [
    ".git/.*",
    "node_modules/.*"
  ],
  "transformIgnorePatterns": [
    "node_modules/.*",
    ".*\\.js"
  ],
  "setupTestFrameworkScriptFile": "<rootDir>/src/setupJest.js",
  "preset": "jest-preset-angular",
  "testEnvironment": "jsdom",
  "testRegex": "src/app/.*\\.spec\\.ts$",
  "moduleFileExtensions": [
    "ts",
    "js",
    "json"
  ],
  "verbose": true,
  "cacheDirectory": ".jest-cache",
  "coveragePathIgnorePatterns": [
    ".*\\.(shim\\.ngstyle|ngfactory)\\.ts"
  ],
  "globals": {
    "ts-jest": {
      "tsConfigFile": "./tsconfig.json"
    },
    "__TRANSFORM_HTML__": true
  }
}

My Jest setup file:

'use strict';
require('core-js/es6/reflect');
require('core-js/es7/reflect');
require('zone.js');
require('zone.js/dist/proxy.js');
require('zone.js/dist/sync-test');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
require('jest-zone-patch');

const getTestBed = require('@angular/core/testing').getTestBed;
const BrowserDynamicTestingModule = require('@angular/platform-browser-dynamic/testing').BrowserDynamicTestingModule;
const platformBrowserDynamicTesting = require('@angular/platform-browser-dynamic/testing')  .platformBrowserDynamicTesting;

getTestBed().initTestEnvironment(
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting()
);

Here is my simple test:

fdescribe('RichTextEditorComponent', () => {
  it('should be fast', () => {
    expect(true).toBeTruthy();
  });
});

Does anyone have any idea as to why this is taking 9+ seconds? 在此处输入图像描述

Another possibility is that ts-jest is slow. There was an issue about that , and it was not completely resolved.

There are various workarounds discussed . They consist of setting isolatedModules=true and also --maxWorkers=1 . That is, in jest.config.js

'use strict';

module.exports = {
    preset: 'ts-jest',
    testEnvironment: 'node',
    globals: {
        'ts-jest': {
            isolatedModules: true
        }
    },
}

and run

yarn test --maxWorkers=1

Could be worth trying. Alternatively, it is possible to forgo ts-jest and use babel transpilation.

Read these two links:

https://itnext.io/how-to-make-your-sluggish-jest-v23-tests-go-faster-1d4f3388bcdd https://github.com/facebook/jest/issues/7963

Here's a list of things to consider. They aren't specific to your case, but since the title of the question is quite general I thought they might help some percentage of visitors. They shouldn't be tried blindly, they are simply a starting point to research.

Things to try to speed up your jest tests:

  1. Run in watch mode with --watch

    jest optimizes when you use --watch .

  2. run on your host computer instead of in docker? -> I was previously using docker exec -it <containername> yarn test and found it faster when I changed to using my host.

  3. upgrade jest version it seems like there were some bugs that made some versions slower https://github.com/facebook/jest/pull/8046

    note: that yarn upgrade obeys the ~ and ^ version signifiers, if you know what you're doing, you might just want to remove and re add yarn remove jest yarn add -D jest that will just get you the latest

  4. change the test environment from jsdom to node

"jest": {
  "testEnvironment": "node"
}
  1. Run the tests syncronously.. allows jest to optimize?

add --runInBand option

  1. Setting max workers might make it faster?

add --maxWorkers=4 option

In my case I upgraded the jest version, started using --watch and --runInBand and running on my host instead of via docker, and my test time went from 2 mins to 10 seconds. I don't know what the problem was exactly in my case.

I think the answer will ultimately need to come from the Angular team. The documentation for platformBrowserDynamicTesting is sparse ( https://angular.io/api/platform-browser-dynamic/testing/platformBrowserDynamicTesting ).

Perhaps platformBrowserDynamicTesting emulates a browser and loads the entire DOM for your application into memory. In this case, a nearly 10 second ramp up for an Angular application (without any cached JavaScript) seems reasonable. Maybe I am interpreting this wrong, but per your reports, it looks like the actual test is running in 6 milliseconds which seems like it should be fulfilling your requirement of a "fast test". I would be curious to see how long the tests take if you add another simple "should be fast 2" test. If the total is still under 10 seconds, that suggests your actual tests are taking very little time in comparison to the ramp up of the Angular platformBrowserDynamicTesting utility.

I solved same issue via installing jest as globally

npm install -g jest@26.0

here is some benchmark results with same project and same test cases

local - win10 version 2004 ----------------- -- node-14.7.0 -- 11.847 s

global - win10 version 2004 ----------------- -- node-14.7.0 -- 0.907 s

global - win10 version 2004 -- wsl/ubuntu-18.04 -- node-14.7.0 -- 0.469 s

2022 - In your jest.config add:

globals: {
  "ts-jest": {
    isolatedModules: true
  }
}

and run

yarn test

I also use Jest on my Angular project and I'm not sure that is a good solution.

When you configure your testing module, you can use NO_ERRORS_SCHEMA and you don't have to add all nested components in declarations to compile the component that you want to test.

beforeEach(async () => {
    return TestBed.configureTestingModule({
      declarations: [
        MyComponent
      ],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  });

Your tests with Jest are unit tests, so with that solution, you will only test your component. If you want to test interaction between components, you will do end-to-end tests with Protractor or Puppeteer.

I am using Jest to test an angular app and it is taking a really long time for simple tests to run and I can not seem to figure out why.

My Jest setup in package.json :

"jest": {
  "modulePaths": [
    "<rootDir>/src",
    "<rootDir>/node_modules"
  ],
  "testPathIgnorePatterns": [
    ".git/.*",
    "node_modules/.*"
  ],
  "transformIgnorePatterns": [
    "node_modules/.*",
    ".*\\.js"
  ],
  "setupTestFrameworkScriptFile": "<rootDir>/src/setupJest.js",
  "preset": "jest-preset-angular",
  "testEnvironment": "jsdom",
  "testRegex": "src/app/.*\\.spec\\.ts$",
  "moduleFileExtensions": [
    "ts",
    "js",
    "json"
  ],
  "verbose": true,
  "cacheDirectory": ".jest-cache",
  "coveragePathIgnorePatterns": [
    ".*\\.(shim\\.ngstyle|ngfactory)\\.ts"
  ],
  "globals": {
    "ts-jest": {
      "tsConfigFile": "./tsconfig.json"
    },
    "__TRANSFORM_HTML__": true
  }
}

My Jest setup file:

'use strict';
require('core-js/es6/reflect');
require('core-js/es7/reflect');
require('zone.js');
require('zone.js/dist/proxy.js');
require('zone.js/dist/sync-test');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
require('jest-zone-patch');

const getTestBed = require('@angular/core/testing').getTestBed;
const BrowserDynamicTestingModule = require('@angular/platform-browser-dynamic/testing').BrowserDynamicTestingModule;
const platformBrowserDynamicTesting = require('@angular/platform-browser-dynamic/testing')  .platformBrowserDynamicTesting;

getTestBed().initTestEnvironment(
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting()
);

Here is my simple test:

fdescribe('RichTextEditorComponent', () => {
  it('should be fast', () => {
    expect(true).toBeTruthy();
  });
});

Does anyone have any idea as to why this is taking 9+ seconds? 在此处输入图片说明

In case anyone dealing with slow execution of jest test suites, Upgrade the version to 25 or above. Jest version 24 runs slow.

https://jestjs.io/blog/2020/01/21/jest-25#performance-improvements[jest-25#performance-improvements][1]

Solution: SWC (Speedy Web Compiler)

ts-jest is most likely slowing down the tests.

SWC is drop-in alternative, written in Rust and super fast . More than 10x improvement for me. link

installation

# if you use npm
npm i -D @swc/core @swc/jest

# if you use yarn
yarn add -D @swc/core @swc/jest

Inside jest.config.js , configure Jest to use SWC:

module.exports = {
  transform: {
    "^.+\\.(t|j)sx?$": ["@swc/jest"],
  },
};

usage

yarn jest --runInBand

note: jest version 28 currently unstable. I use 27.0.4

Alternative: ESBuild

use can also use esbuild written in Go , also very fast. (similar performance to swc)

yarn add -D esbuild-jest esbuild

Inside jest.config.js , configure Jest to use esbuild

module.exports = {
  transform: {
    "^.+\\.(t|j)sx?$": ["esbuild-jest"],
  },
};

inspired by speeding-up-jest

My tests were running very slow due to this issue with faker (version: 7.3.0 ).

Using const { faker } = require('@faker-js/faker/locale/en_US'); instead of const { faker } = require('@faker-js/faker'); sped up the require statement by about 50 seconds.

Took a while for me to hunt down the bugger

Eventually what worked for me is to profile the jest test and look through to identify what is causing the slow jest startup. You can use this video to help.

For me it was the @mui/icons-material library. after uninstalling it, running a single file went from 5s to 2s.

Alternative I found:

// Instead of destructuring like such:
import { ExpandMore } from "@mui/icons-material"

// Directly importing speeds up by 3s
import ExpandMore from "@mui/icons-material/ExpandMore"

related: https://github.com/mui/material-ui/issues/12422

related: https://github.com/facebook/jest/issues/10833#issuecomment-1192232331

Using docker and having a volume mounted for node_modules caused the tests to be very slow.

Removing the mounted volume on node_modules sped up the tests by about 60 seconds.

See the following links for more details on this.

  1. https://stackoverflow.com/a/47564342/9530790
  2. https://stackoverflow.com/a/49081609/9530790

Having a file watcher while using jetbrains slowed my tests by about 100%.

I noticed this when I closed down my jetbrains ide and my tests ran over 100% faster.

Downgrading form jest ^29.xx to ^26.6.3 more than doubled my jest speed to a more reasonable time of a few seconds instead of double digit seconds.

Just in case, if your test cases are taking too long because of the hardware you are using.

You may get the error:

  thrown: "Exceeded timeout of 5000 ms for a hook.
  Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

To avoid this error you can increase the timeout in the command line using the --testTimeout <TIME_IN_MILLI_SECONDS> option eg here I've used the 50 seconds

jest --testTimeout 50000

Note: The default timeout is 5000 ms (5 seconds).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM