当我运行笑话测试时,每个测试使用的内存量会随着时间的推移而增加。这个问题在我的本地机器上并不明显;相反,我在 CircleCI 上运行测试时发现了这一点。我收到以下错误:
FAIL __tests__/pages/login.test.tsx
● Test suite failed to run
jest: failed to cache transform results in: /tmp/jest_2ne/jest-transform-cache-7bdebd1a0c578519274d14a78b89f87c-f8238a99880aac6151736010e575fab1/0b/symbols_0bf4cffb45cb261625f2f3fca21a4789.map
Failure message: ENOMEM: not enough memory, write
at writeFileSync (node_modules/write-file-atomic/index.js:215:10)
at writeCacheFile (node_modules/@jest/transform/build/ScriptTransformer.js:809:33)
at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:7)
at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:586:40)
at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:624:25)
如何修复我的笑话配置以防止出现这种情况?
首先,通过使用以下选项运行 jest 来确保您进行了泄漏测试:
jest --logHeapUsage
运行测试并检查内存消耗是否随着时间的推移而增加,如下所示(文件名已更改):
PASS __tests__/pages/file.test.tsx (181 MB heap size)
PASS __tests__/pages/file2.test.tsx (193 MB heap size)
PASS __tests__/components/Header/file3.test.tsx (201 MB heap size)
PASS __tests__/components/Header/file4.test.tsx (192 MB heap size)
PASS __tests__/components/Header/file5.test.tsx (218 MB heap size)
PASS __tests__/pages/file6.test.tsx (201 MB heap size)
PASS __tests__/components/file6.test.tsx (203 MB heap size)
PASS __tests__/components/file7.test.tsx (213 MB heap size)
PASS __tests__/components/file8.test.tsx (234 MB heap size)
PASS __tests__/components/file9.test.tsx (222 MB heap size)
PASS __tests__/components/file10.test.tsx (240 MB heap size)
PASS __tests__/components/file11.test.tsx (231 MB heap size)
PASS __tests__/utils/file12.test.tsx (239 MB heap size)
PASS __tests__/components/file13.test.tsx (251 MB heap size)
PASS __tests__/components/file14.test.tsx (239 MB heap size)
PASS __tests__/components/file15.test.tsx (249 MB heap size)
PASS __tests__/components/file16.test.tsx (143 MB heap size)
要解决此问题,请将
npm run test
中的 yarn test
或 package.json
命令更改为:
node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage
运行命令。这是我的输出:
PASS __tests__/components/file.test.tsx (143 MB heap size)
PASS __tests__/pages/onboarding/file1.test.tsx (149 MB heap size)
PASS __tests__/components/file2.test.tsx (146 MB heap size)
PASS __tests__/components/file3.test.tsx (146 MB heap size)
PASS __tests__/components/file4.test.tsx (153 MB heap size)
PASS __tests__/components/Header /file5.test.tsx (149 MB heap size)
PASS __tests__/pages/file6.test.tsx (149 MB heap size)
PASS __tests__/pages/file7.test.tsx (149 MB heap size)
PASS __tests__/components/file8.test.tsx (147 MB heap size)
PASS __tests__/components/file9.test.tsx (148 MB heap size)
PASS __tests__/pages/file10.test.tsx (148 MB heap size)
PASS __tests__/components/Header /file11.test.tsx (148 MB heap size)
PASS __tests__/functions/file12.test.tsx (149 MB heap size)
PASS __tests__/components/file13.test.tsx (148 MB heap size)
PASS __tests__/components/file14.test.tsx (150 MB heap size)
PASS __tests__/components/file15.test.tsx (150 MB heap size)
PASS __tests__/components/Header /file16.test.tsx (149 MB heap size)
PASS __tests__/components/file17.test.tsx (149 MB heap size)
PASS __tests__/utils/file18.test.tsx (150 MB heap size)
PASS __tests__/components/file19.test.tsx (149 MB heap size)
PASS __tests__/pages/file20.test.tsx (150 MB heap size)
如您所见,内存消耗更加一致。
您可以在这个 Github 问题中阅读有关此问题和解决方案的更多信息,其中描述了 jest 的垃圾收集器泄漏问题。
我在运行集成测试时遇到了同样的问题,最初堆大小约为 160MB,本地爬升至约 1600MB,并在 CI 中出现 OOM。这个问题还导致随机测试开始失败,并显示
Exceeded timeout of 5000 ms for a test.
workerIdleMemoryLimit
标志:
// jest.config.js
/** @type {import('jest').Config} */
const config = {
workerIdleMemoryLimit: '512MB',
};
module.exports = config;
环境:
更改配置后,堆大小保持在限制以下并修复了超时失败问题。
作为额外的好处,测试在本地运行速度更快约 20 秒,在 CI 中运行速度约 4 分钟(使用
--maxWorkers 4
cli 选项)
您可以使用
jest -w 1
来避免这些内存问题。
--maxWorkers=|# 别名:-w.指定工作池为运行测试而生成的最大工作人员数量。在单次运行中 模式,默认为您的可用核心数 机器主线程减一。在观看模式下,默认为 机器上一半的可用内核,以确保 Jest 不引人注目,不会让您的机器停止运转。可能是 在 CI 等资源有限的环境中调整这一点很有用,但是 默认值应该足以满足大多数用例。
我的环境是:
我运行测试的 npm 脚本是
jest --coverage
。当我运行测试时,出现此错误
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
使用
v8
作为承保提供商对我有用。
// Example jest.config.js
module.exports = {
coverageProvider: 'v8', // Default is 'babel'
transform: {
'\\.[jt]sx?$': 'ts-jest'
}
};
参考。 https://jestjs.io/docs/configuration#coverageprovider-string
就我而言,当我使用复杂对象时就会发生这种情况:
expect(spyFn).toHaveBeenCalledWith(COMPLEX_OBJECT_WITH_DIFFICULT_STRUCTURE);
因此,当您使用 jest toEqual 实用程序时,您可能会遇到 堆内存不足错误(它递归地比较对象的所有属性)。
作为解决方案,尝试用“simplifiedObject”替换“complexObject”:
切换到节点版本 16.10 解决了我的问题。显然,jest 的内存泄漏仅发生在节点版本 > 16 的情况下。 我只是使用 NVM 通过运行
nvm install 16.10
首先安装节点 16.10。完成此操作后,运行我的玩笑测试使用了 555MB,而不是 1.5GB 内存。
什么对我不起作用:
--max-old-space-size
--no-compilation-cache
--runInBand
--expose-gc
--maxWorkers
--workerIdleMemoryLimit
--clearMocks
jest.clearAllMocks()
添加到每个套件上的
beforeEach
的结果相同)在这一个上绕了一圈房子 -
workerIdleMemoryLimit
似乎只在套件之间工作,而不是在每次测试之间工作(根据文档)所以也通过设置它并分割我的较大套件来使其工作,但并不高兴以此作为最终修复。
这将有助于加速测试运行和解决堆内存问题
--workerIdleMemoryLimit=350
,如下所示jest --env=jsdom --verbose a --coverage --max-old-space-size=16384 --silent --logHeapUsage --workerIdleMemoryLimit=350
isolatedModules: true
,如下所示变换:{ '^.+\.ts?$': ['ts-jest', { 隔离模块:true }] }