Guide to jest and @swc/jest

使用正确的姿势使用 jest 或 @swc/jest

Config Jest

testEnvironmentOptions

Loading subresources

By default, jsdom will not load any subresources such as scripts, stylesheets, images, or iframes. If you'd like jsdom to load such resources, you can pass the resources: "usable" option, which will load all usable resources. Those are:

  • Frames and iframes, via <frame> and <iframe>
  • Stylesheets, via <link rel="stylesheet">
  • Scripts, via <script>, but only if runScripts: "dangerously" is also set
  • Images, via <img>, but only if the canvas npm package is also installed (see "Canvas Support" below)

When attempting to load resources, recall that the default value for the url option is "about:blank", which means that any resources included via relative URLs will fail to load. (The result of trying to parse the URL /something against the URL about:blank is an error.) So, you'll likely want to set a non-default value for the url option in those cases, or use one of the convenience APIs that do so automatically.

reporters

https://jestjs.io/docs/configuration#reporters-arraymodulename--modulename-options

GitHub Actions Reporter
If included in the list, the built-in GitHub Actions Reporter will annotate changed files with test failure messages and (if used with 'silent: false') print logs with github group features for easy navigation. Note that 'default' should not be used in this case as 'github-actions' will handle that already, so remember to also include 'summary'. If you wish to use it only for annotations simply leave only the reporter without options as the default value of 'silent' is 'true':

/** @type {import('jest').Config} */ const config = { reporters: [ [ 'github-actions', { silent: false, }, ], 'summary', ], }; module.exports = config;

Jest CLI Options

Using MaxWorkers=50% to get the optimal performance.

https://jestjs.io/docs/cli#--maxworkersnumstring

Alias: -w. Specifies the maximum number of workers the worker-pool will spawn for running tests. In single run mode, this defaults to the number of the cores available on your machine minus one for the main thread. In watch mode, this defaults to half of the available cores on your machine to ensure Jest is unobtrusive and does not grind your machine to a halt. It may be useful to adjust this in resource limited environments like CIs but the defaults should be adequate for most use-cases.

For environments with variable CPUs available, you can use percentage based configuration: --maxWorkers=50%

--shard

The test suite shard to execute in a format of (?<shardIndex>\d+)/(?<shardCount>\d+).

shardIndex describes which shard to select while shardCount controls the number of shards the suite should be split into.

shardIndex and shardCount have to be 1-based, positive numbers, and shardIndex has to be lower than or equal to shardCount.

When shard is specified the configured testSequencer has to implement a shard method.

For example, to split the suite into three shards, each running one third of the tests:

jest --shard=1/3 jest --shard=2/3 jest --shard=3/3

@swc/jest with @emotion/react

fix: toMatchSnapshot

const { pathsToModuleNameMapper } = require('@powerfulyang/lint'); const tsconfig = require('./tsconfig.json'); const moduleNameMapper = pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: '<rootDir>/', }); const esModules = ['d3', 'internmap', 'delaunator', 'robust-predicates'].join('|'); /** @type {import('jest').Config} */ module.exports = { moduleNameMapper: { ...moduleNameMapper, // Handle CSS imports '^.+\\.(css|sass|scss)$': require.resolve('./__mocks__/styleMock.js'), // Handle image imports '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$': require.resolve(`./__mocks__/fileMock.js`), }, setupFilesAfterEnv: ['<rootDir>/.jest/jest.setup.ts'], transform: { '.*\\.(tsx?|jsx?)$': [ '@swc/jest', { jsc: { transform: { react: { runtime: 'automatic', importSource: '@emotion/react', }, }, }, }, ], }, testEnvironment: 'jsdom', transformIgnorePatterns: [`node_modules/.pnpm/(?!${esModules})`], snapshotSerializers: [ '@emotion/jest/serializer' /* if needed other snapshotSerializers should go here */, ], };

问题解决方案

测试超时问题

Error: thrown: "Exceeded timeout of 5000 ms for a hook. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

不希望加上全局超时时间,可以给单个测试设置,afterAll, beforeAll 等都可以设置。

在Jest中,你可以为单个测试设置超时。通常,我们在test或者it函数的第三个参数中设置超时值(以毫秒为单位)。例如:

javascript
1test('my test', (done) => {
2  // Your test code here
3}, timeout_in_milliseconds);

这里的timeout_in_milliseconds就是你希望设定的超时时间,以毫秒为单位。例如,如果你想要设定超时时间为10秒,你可以这样写:

javascript
1test('my test', (done) => {
2  // Your test code here
3}, 10000); // 10000 milliseconds = 10 seconds

如果你的测试函数是一个异步函数,你可以这样写:

javascript
1test('my async test', async () => {
2  // Your test code here
3}, 10000); // 10000 milliseconds = 10 seconds

这样,这个测试在10秒后还没有完成的话,Jest就会自动将其标记为失败。

TimeoutOverflowWarning: Infinity does not fit into a 32-bit signed integer. Timeout duration was set to 1.

Jest 使用 Node.js 的 setTimeout 函数来实现超时,这个函数只能接受一个32位有符号整数作为超时时间。这意味着超时时间的最大值是 2,147,483,647 毫秒,或者大约24.8天。任何超过这个值的超时时间,包括 Infinity,都会被设置为1毫秒,你看到的警告就是这个原因。

如果你的测试用例需要的时间超过了这个限制,你可能需要重新考虑你的测试策略。例如,你可以尝试将一个大的测试用例拆分为多个小的测试用例,或者使用模拟(mocking)或存根(stubbing)来模拟一些耗时的操作。

总的来说,尽管技术上你可以尝试设置一个非常大或无限的超时时间,但在实际应用中,你应该尽量避免让测试用例运行过长的时间。良好的测试应当是可重复的、独立的,并且在合理的时间内完成。