ts-jest: Unit test runs very slow (6 sec per a test)

  • Issue

After config ts-jest to create-react app successfully, I saw a test case run 6s. That’s very slow. My jest config following the document: (ts|tsx)": “<rootDir>/node_modules/ts-jest/preprocessor.js”

My code

describe("App", () => {
    it("renders only 1 App component", () => {
        const component = shallow(<App />);
        console.log(component.html())
        expect(component).toHaveLength(1);
    });
});

Result: PASS src/containers/test/App.spec.tsx (6.119s)

  • Expected behavior

I searched some tutorials on the internet, there is a preprocessor.js file:

const tsc = require("typescript");
const tsConfig = require("./tsconfig.json");

module.exports = {
  process(src, path) {
    if (path.endsWith(".ts") || path.endsWith(".tsx")) {
      return tsc.transpile(src, tsConfig.compilerOptions, path, []);
    } else if (path.endsWith(".js") ) {
      return tsc.transpile(src, tsConfig.compilerOptions, path, []);
    }
    return src;
  }
};

If I use this file, the test case runs on 3 -4s. Can you explain me this problem? Does preprocessor.js of TS-Jest have more functionalities than that file as well?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 67
  • Comments: 79 (6 by maintainers)

Commits related to this issue

Most upvoted comments

If you’re having trouble with this, you could try running jest with --maxWorkers=1 or --runInBand. We were having very slow tests too, but running it with only one worker (which is what both of those commands do) reduced our run time by 95% in a local dev test. Seems counter-intuitive, but it’s working. runInBand says it’s intended for debugging purposes, so I’d stick to the maxWorkers flag if it works for you.

@EvanDarwin I am experiencing issues with slow tests too. It can take around 30-50 seconds for a single test. Were you able to resolve it?

Using the node-inspector I’ve found a potential reason for the slowness:

screen shot 2017-08-04 at 13 32 54

Every time a Error is created the stacktrace is prepared and this retriggers the Typescript transpile step. Weird, as Typescript already compiled. What causes this I don’t know. Does ts-lint manually patch some of these methods to inject the TS compile step? And if so, doesn’t that need to use some sort of cache?

Funny, how are people concerned about 6s tests … look at this 😕

PASS src/segments/order/molecules/__tests__/OrderWarePriceLine.test.tsx (34.491s)
PASS src/segments/order/atoms/__tests__/OrderListTitle.test.tsx (34.304s)
PASS src/molecules/__tests__/ConfirmButton.test.tsx (36.691s)
PASS src/atoms/__tests__/Sizer.test.tsx (36.435s)
PASS src/segments/createorder/hooks/__tests__/useOrderMenuFilter.test.tsx (37.375s)

And these are times from the Bitbucket Pipelines, so it’s not like something is slowing it down on my local system. Locally I am getting slightly higher times (+5-10s). I’ve tried to disable diagnostics, but there was no difference really.

For a reference, when I try to run a simple test with expect(true).toBe(true) only, it already takes about 6-10 seconds, so it’s not like there would be some heavy code on my side.

It’s very sad. I love Typescript and Jest, why can’t these live together peacefully?

jest 23.6.0 ts-jest 23.10.5

Config is variation on CRA version (output with --showConfig)
{
  "configs": [
    {
      "automock": false,
      "browser": false,
      "cache": true,
      "cacheDirectory": "C:\\Users\\krejc\\AppData\\Local\\Temp\\jest",
      "clearMocks": false,
      "coveragePathIgnorePatterns": [
        "\\\\node_modules\\\\"
      ],
      "detectLeaks": false,
      "detectOpenHandles": false,
      "errorOnDeprecated": false,
      "filter": null,
      "forceCoverageMatch": [],
      "globals": {
        "ts-jest": {
          "diagnostics": false,
          "tsConfig": {
            "jsx": "preserve",
            "module": "ESNext"
          },
          "babelConfig": {
            "plugins": [
              "babel-plugin-macros",
              "@babel/plugin-syntax-dynamic-import",
              "@lingui/babel-plugin-transform-react",
              "@lingui/babel-plugin-transform-js",
              "@babel/plugin-transform-react-jsx",
              "@babel/plugin-transform-modules-commonjs"
            ]
          }
        }
      },
      "haste": {
        "providesModuleNodeModules": []
      },
      "moduleDirectories": [
        "node_modules"
      ],
      "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "jsx",
        "json"
      ],
      "moduleNameMapper": [
        [
          "^.+\\.module\\.css$",
          "identity-obj-proxy"
        ]
      ],
      "modulePathIgnorePatterns": [],
      "name": "605e4449eee795b9cb0d5646eb3442a2",
      "prettierPath": "D:\\workspace\\app\\node_modules\\prettier\\index.js",
      "resetMocks": false,
      "resetModules": false,
      "resolver": null,
      "restoreMocks": false,
      "rootDir": "D:\\workspace\\app\\src",
      "roots": [
        "D:\\workspace\\app\\src"
      ],
      "runner": "jest-runner",
      "setupFiles": [],
      "setupTestFrameworkScriptFile": "D:\\workspace\\app\\src\\setupTests.js",
      "skipFilter": false,
      "snapshotSerializers": [],
      "testEnvironment": "D:\\workspace\\app\\node_modules\\jest-environment-jsdom\\build\\index.js",
      "testEnvironmentOptions": {},
      "testLocationInResults": false,
      "testMatch": [
        "D:\\workspace\\app\\src\\**\\__tests__\\**\\*.ts?(x)"
      ],
      "testPathIgnorePatterns": [
        "\\\\node_modules\\\\"
      ],
      "testRegex": "",
      "testRunner": "D:\\workspace\\app\\node_modules\\jest-jasmine2\\build\\index.js",
      "testURL": "http://localhost",
      "timers": "real",
      "transform": [
        [
          "^.+\\.tsx?$",
          "D:\\workspace\\app\\node_modules\\ts-jest\\dist\\index.js"
        ],
        [
          "^.+\\.css$",
          "D:\\workspace\\app\\node_modules\\react-scripts-ts\\config\\jest\\cssTransform.js"
        ],
        [
          "\\.(gql|graphql)$",
          "D:\\workspace\\app\\node_modules\\jest-transform-graphql\\index.js"
        ],
        [
          "^(?!.*\\.(js|jsx|css|json)$)",
          "D:\\workspace\\app\\node_modules\\react-scripts-ts\\config\\jest\\fileTransform.js"
        ]
      ],
      "transformIgnorePatterns": [
        "[\\\\\\\\]node_modules[\\\\\\\\].+\\.(js|jsx|ts|tsx)$"
      ],
      "watchPathIgnorePatterns": []
    }
  ],
  "globalConfig": {
    "bail": false,
    "changedFilesWithAncestor": false,
    "collectCoverage": false,
    "collectCoverageFrom": [
      "**/*.{ts,tsx}",
      "!**/*.d.ts"
    ],
    "coverageDirectory": "D:\\workspace\\app\\src\\coverage",
    "coverageReporters": [
      "json",
      "text",
      "lcov",
      "clover"
    ],
    "coverageThreshold": null,
    "detectLeaks": false,
    "detectOpenHandles": false,
    "errorOnDeprecated": false,
    "expand": false,
    "filter": null,
    "globalSetup": null,
    "globalTeardown": null,
    "listTests": false,
    "maxWorkers": 7,
    "noStackTrace": false,
    "nonFlagArgs": [],
    "notify": false,
    "notifyMode": "always",
    "passWithNoTests": false,
    "projects": null,
    "rootDir": "D:\\workspace\\app\\src",
    "runTestsByPath": false,
    "skipFilter": false,
    "testFailureExitCode": 1,
    "testPathPattern": "",
    "testResultsProcessor": null,
    "updateSnapshot": "new",
    "useStderr": false,
    "verbose": false,
    "watch": false,
    "watchman": true
  },
  "version": "23.6.0"
}

Not sure if this is the intended speed, but I just started writing tests and for a single file I get ~6s every time in watch mode, but the actual tests take about 150-200ms. Output:

 PASS  src/__tests__/createServer.test.ts
  createServer
    ✓ should be defined (5ms)
    ✓ should start a working server (120ms)
    ✓ server should return a valid scheme (40ms)

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   1 passed, 1 total
Time:        6.484s
Ran all test suites related to changed files.

jest 23.6.0 ts-jest 23.10.5

Same issue here, i’m using it on a Nest.js project, but it still use ts-jest under the hood so… Even basic tests like @cookernetes have shown takes 20 seconds !

I’m currently using the 29.0.3 version

It’s worth to mention that I managed to fix my issue by adding the isolatedModules: true flag to my ts-jest config. Tests no longer take 10 mins but still there’s considerable slowdown compared to 23.1.4 from 56s to 120-200s for suite of > 1800 tests.

Judging on the number of upvotes, I’m reopening this.

Install SWC with

pnpm add -D @swc/core @swc/jest

And add this to your jest.config.js

{
  "transform": {
    "^.+\\.(t|j)sx?$": "@swc/jest"
  }
}

If you wish, you can use this workaround in jest.config.js:

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

Reduced complex tests time from 7 seconds to 2.7 seconds and times are much more consistent.

Sad to see that this issue has persisted so long. I can’t continue using this library in good faith for future projects knowing that it’ll take 1m+ for a small test suite to run. I switched to mocha with ts-mocha:

  17 passing (126ms)

My observations (and I don’t know much about jest internals or ts-jest internals, so take with a grain of salt):

  • jest workers run independently of each worker. This results in:
  • Every jest worker compiles typescript on each own. 8 workers = 8 compilations in parallel. Therefore tests are very slow.
  • On second run, cache should kick in, but well, it seems like it doesn’t happens. Therefore multiple executions are still slow. Probably a bug.
  • runInBand or maxWorkers: 1 seems like allowing re-usage of compiled artifacts, because there is only one worker (and caches compiled artifacts in memory?). Therefore, the compilation of first testsuit is still slow (but faster than with multiple compilations in parallel), but following testsuits are very fast and, probably, compiles needed files incrementally.
  • isolatedModules turns type checking off. Therefore compiler do less work and the tests are faster, especially if run in parallel.

All in one, I try following workaround now:

  • Use isolatedModules in development for speed
  • Use maxWorkers: 1 in CI to ensure types

I hope that the issue with caching can be pinned down and resolved.

@ahnpnl can you please reopen this issue?

Related, but I don’t think that it is the same: https://github.com/kulshekhar/ts-jest/issues/1310 Unrelated: https://github.com/kulshekhar/ts-jest/issues/1115

Please don’t forget that this is also used in large corporate projects with CI and many contributors. If CI isn’t doing type checking, there’s a big possibly of issues getting into master even in if PR reviews are part of the process.

Well, but still, you can have your type-checking executed before tests. Simple tsc --noEmit and you are golden. That must be definitely faster as it won’t need to re-check each and every file again when multiple tests are using it.

I don’t see any benefits of type checking during the test run. It’s a runtime code that matters after all.

@Loremaster I’m still having this issue… however many months later.

 PASS  src/lib/__tests__/crypto.test.ts (6.849s)
 PASS  src/lib/__tests__/detect.test.ts (6.828s)
 PASS  src/lib/__tests__/ErrorList.test.ts (7.195s)
 PASS  src/es-entity/__tests__/Video.test.ts (8.656s)
 PASS  src/lib/__tests__/boards.test.ts (8.245s)
 PASS  src/lib/__tests__/routes.test.ts (16.646s)

These are very basic tests, and shouldn’t take longer than 1s. Running jest 23.6.0, ts-jest 23.10.5, typescript 3.2.4.

I know that this issue has been closed but I’m experiencing this issue across three different projects. It seems like the tests are running sequentially, and jest is waiting for the previous test to finish before running other. This leaves me with tests that have a runtime of 50+ seconds for a single test on our largest project.

All projects are running ts-jest 22.4.6, jest 23.0.1. Here are my configurations (for the smallest, simplest project I have): https://gist.github.com/EvanDarwin/54adb53381551562c0df64ca6abf35a0

@bbugh --maxWorkers=1 works quite well in the CodeSandbox container I’m currently working in!

The difference is quite large 🤯:

cold start

before: up to 12 seconds after: 3 seconds

--watchAll incremental re-test

before: 8-12 seconds after: 0.1 seconds

Before (incremental re-test)

Screen Shot 2019-06-27 at 11 17 24

After (incremental re-test)

Screen Shot 2019-06-27 at 11 16 07

CodeSandbox Demo (--maxWorkers=1 already enabled in package.json):

https://codesandbox.io/s/nodejs-ts-w-ts-jest-jest-runner-eslint-frozen-public-demo-hdvxn

@bbugh your fix brought the time down from 30 seconds to 7. What is it about multiple workers that, not only gives no performance increase but actually makes it far worse?

Is this still the best issue to track for this? Has anyone found any solution or further information on this? We left jest out of our project due to this and I was hoping to bring it back in, but it looks like this is probably still an issue after 6 months. (Apologies for the notification spam, but I figured after 6 months and +50 votes it was worth someone asking a follow-up in text).

@kulshekhar It appears that v24 has suffered major performance regression. I’m reverting back to v23.1.4, which performs like a champion.

or using isolatedModules: true

Hi all, would you guys help testing with the new changes mentioned in https://github.com/kulshekhar/ts-jest/issues/1310#issuecomment-571335754 ?

@bbugh It’s a life saver!

Well, seems like the problem was with jest-webpack-resolver https://github.com/mkg0/jest-webpack-resolver bumped its’ dependencies (from webpack resolve 2.6.x to 3.4.x) and test run time is cut almost in half (11 instead of 18-20sec).

Tested 20.0.10 - no visible improvement. Rather small test environment of 65 tests runs 18-20 seconds. 7 of 11 suites comprising those 65 tests took longer than 5 seconds.

@kompot would it be possible for you to create a sample repo with one of the long running tests?

wow, this really made our tests a lot faster!

@kryops awesome!

Is the cache in #292 specific to source-map-support, or is it the cache from the first compilation that also generated the tests to be run?

@hermanbanken That cache is specific to source-map-support. The cache from the first compilation is handled by jest and not by ts-jest.

Anyway, good work!

Thanks. You deserve the bulk of the credit for this though. The repo and the profile were immensely helpful.

At this point, I think any significant speed improvement beyond this might have to come from Jest itself

I’m still facing the issue now. A very simple test of checking 1+1 equals 2 takes 6s. Doing the --maxWorkers=1 trick seems helping a lot, reducing the time to 0.5s.

FYI: https://github.com/kulshekhar/ts-jest/pull/1549 will be in alpha version of ts-jest (possibly today). Anyone who is using ts-jest please help to test the alpha version and give us some feedbacks for https://github.com/kulshekhar/ts-jest/issues/1115

No I don’t mean addresses by a workaround. I mean workaround is isolatedModule=true. By default, isolatedModule=false which causes the issue. Since this has been linked to the other issue as related area (performance after 23.10, I don’t see any issues of closing this. You can always look back from the link issue

@ahnpnl Has been addressed by a workaround 😆? If there is an existing issue that tracks performance after 23.10, can you link it here, please? Otherwise, I don’t follow either why to close this one. Plenty of valuable feedback here.

@bbugh Thanks very much, and thank you for coming up with the workaround/fix.

@alexgorbatchev Hey you think you have ts-jest slow? PASS src/redux/epics.test.ts (1371.894s) And I have absolutely no clue why that is. Running jest --no-cache absolutely kills it. Initial tests are always > 10m on ts-jest 24.0.2 whereas on 23.1.4 the whole suite of over 1800 tests passes in 56 seconds.

3ms + 1ms + 1ms (simple string manipulations) = 5.4s.

ConEmu64_2019-04-13_01-21-11

I am also seeing a substantial increase in test time between 20.0.4 and 20.0.7.

  • Node 6.11.1
  • TypeScript 2.4.2
  • Windows 10
  • 84 tests in 25 suites, 40 snapshots - most of the tests are fairly heavy, lots of React application mounting through enzyme

ts-jest 20.0.4: 30-35s ts-jest 20.0.7: ~60s

It’s sadly not open source, the only thing I am able to provide is our jest.json:

jest.json
{
    "setupTestFrameworkScriptFile": "<rootDir>/node_modules/project-watchtower/lib/test/setup-tests.js",
    "transform": {
        ".tsx?": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "transformIgnorePatterns": [
        "node_modules/(?!swm-component-library)"
    ],
    "testRegex": "\\.(spec|test)\\.tsx?$",
    "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "json"
    ],
    "moduleDirectories": [
        "node_modules"
    ],
    "modulePaths": [
        "<rootDir>/common",
        "<rootDir>/app",
        "<rootDir>"
    ],
    "moduleNameMapper": {
        "\\.(s?css|png|svg|jpg)$": "<rootDir>/node_modules/project-watchtower/lib/test/test-mapper.js",
        "^bundle-loader": "<rootDir>/node_modules/project-watchtower/lib/test/bundle-loader-mapper.js"
    },
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ],
    "verbose": false,
    "collectCoverageFrom": [
        "**/*.{ts,tsx}",
        "!**/*.d.ts",
        "!**/node_modules/**",
        "!config/**"
    ],
    "coverageReporters": ["json", "lcov", "text", "teamcity"],
    "testResultsProcessor": "jest-teamcity-reporter",
    "rootDir": "../../../.."
}