我有一个大型 React 应用程序,在 CI 中运行了 4205 个 Jest 测试,运行所有测试需要 40 多分钟。这个时间正常吗?
版本:
NPM: 7.24.0
Node: 16.10.0
@testing-library/jest-dom: 6.4.2
@testing-library/react: 12.1.5
@testing-library/user-event: 14.5.2
jest: 29.7.0
jest-canvas-mock: 2.3.1
jest-environment-jsdom: 29.4.0
jest-junit: 16.0.0
jest-sonar: 0.2.16
jest-transform-stub: 2.0.0
jsdom: 21.1.0
jest.config.js:
module.exports = {
clearMocks: true,
restoreMocks: true,
moduleNameMapper: {
//some options
},
setupFiles: ["<rootDir>/buildTools/define-deprecated-global.js"],
setupFilesAfterEnv: ["<rootDir>/buildTools/setupTests.js"],
transform: {
//some options
},
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
testEnvironment: "jsdom",
testPathIgnorePatterns: ["/test.js"],
testTimeout: 250000,
coverageDirectory: "target/coverage",
collectCoverage: true,
coverageReporters: ["json", "lcov", "clover"],
reporters: [
//some entries
]
};
package.json脚本:
"test:ci": "node --max-old-space-size=8192 --experimental-vm-modules node_modules/.bin/jest --maxWorkers=20% --watchAll=false --silent",
最近我尝试将 package.json 更改为这个,但时间增加了:
"test:ci": "node --optimize-for-size --max-old-space-size=8192 --gc_interval=100 --concurrent-recompilation --no-compilation-cache --experimental-vm-modules node_modules/.bin/jest --maxWorkers=50% --watchAll=false --silent --ci",
有什么建议可以改进吗?还有更好的配置吗?除了 Jest 还有更好的替代品吗? 我知道 Node 20 修复了内存泄漏问题,但我已经尝试过 Node 20,测试时间仍然很长。
可能的帮助:
无编译缓存
我遵循了这个建议 https://dev.to/retyui/resolve-memory-leaks-caused-by-jest-with-nodejs-16x-and-18x-javascript-heap-out-of-memory-3md5并刚刚添加
--no-compilation-cache
到 package.json 但我没有看到任何改进。
静态maxWorkers
我发现
--maxWorkers
在CI环境中效果不太好。我向 CI 构建请求 9000m(9 核)CPU。使用 --maxWorkers=20%
,有时测试会使用 9 个核心,有时使用 6 个核心,有时使用 4 个核心。因此,如果我请求 9000m,可能最好使用 --maxWorkers=9
或 --maxWorkers=7
。
覆盖范围
我在某处读到,在测试执行期间收集测试覆盖率可以增加测试执行时间。所以我正在考虑将测试覆盖率收集转移到 CI 的不同阶段。
为此,我相信,在 package.json 中,我需要添加另一个命令并在新的 CI 阶段中调用它:
"test:coverage": "jest --coverage"
。
在我的jest.config.js中,我需要在测试执行期间禁用覆盖率收集:
collectCoverage: false
。
承诺
我总是对 Promise 格外小心,因为我知道它们会成倍地增加我的测试时间,并且可能会导致多次不稳定的测试。 所以我:
async-await
而不是 .then()
;.then()
;await
为了承诺的结果。如果我不确定一个函数是否会返回一个promise,我会检查它将返回什么样的结果,如果是一个promise,所以我显然需要await
;async
或 / 和 await
。我注意到,如果代码中错误地使用了任何 async
或 / 和 await
,则会导致测试中出现一些不稳定的情况。为了防止其中一些情况,我在我的 .eslintrc.json:
中添加了这些规则"require-await": "error",
"no-return-await": "error",
另一个建议是使用这个:https://www.npmjs.com/package/eslint-plugin-promise
我想知道这样做是否会增加内存泄漏(因为我有很多这样的测试):
functionToBeTested() {
requestSomeThingToTheServer(123).then(apiResult => {
doSomething(apiResult);
doSomethingMore();
});
}
test("check the Server request", (done) => {
mockServerRequest((requestParams) => { //is mocking requestSomeThingToTheServer() action
expect(requestParams).toEqual(123);
done();
});
functionToBeTested();
});
Promise 被存储在内存中,直到它们被清除之前它们不会被清除。 要么处理要么拒绝
所以如果我在 Promise 执行期间在测试中使用
done()
,它的内存将不会被清除并且可能会出现问题?
维斯特
我正在强烈考虑迁移到 Vitest。人们说它比 Jest 更快,而且迁移似乎并不困难:
反应18
我还没有使用 React 18,但我很担心:https://github.com/testing-library/react-testing-library/issues/1235
React 18 似乎测试时间会增加更多。
一些额外信息
https://apidog.com/blog/jest-test-running-concurrently/ https://snird.medium.com/do-not-use-node-js-optimization-flags-blindly-3cc8dfdf76fd https://gist.github.com/stormwild/4bd3c1ec50ed055a363012a403b16365 https://www.npmjs.com/package/eslint-plugin-promise