【发布时间】:2015-12-21 11:40:52
【问题描述】:
我正在通过 npm test 运行 Jest 测试。 Jest 默认并行运行测试。有什么方法可以让测试按顺序运行吗?
我有一些测试调用依赖于更改当前工作目录的第三方代码。
【问题讨论】:
标签: jestjs
我正在通过 npm test 运行 Jest 测试。 Jest 默认并行运行测试。有什么方法可以让测试按顺序运行吗?
我有一些测试调用依赖于更改当前工作目录的第三方代码。
【问题讨论】:
标签: jestjs
CLI options are documented 也可以通过运行命令jest --help 访问。
您会看到您正在寻找的选项:--runInBand。
【讨论】:
npm test --runInBand吗?题外话:不知道“乐队”这个名字是从哪里来的。 --runSequentially 可能更有意义:)
npm test -- --runInBand 是正确的。
我仍然熟悉 Jest,但似乎描述块同步运行,而测试块异步运行。我在看起来像这样的外部描述中运行多个描述块:
describe
describe
test1
test2
describe
test3
在这种情况下,test3 在test2 完成之前不会运行,因为test3 位于包含test2 的描述块之后的描述块中。
【讨论】:
describe 不是必需的。
它对我很有用,可确保按顺序运行很好地分离到模块的测试:
1) 将测试保存在单独的文件中,但在命名时不带spec/test。
|__testsToRunSequentially.test.js
|__tests
|__testSuite1.js
|__testSuite2.js
|__index.js
2) 包含测试套件的文件也应如下所示(testSuite1.js):
export const testSuite1 = () => describe(/*your suite inside*/)
3) 将它们导入到testToRunSequentially.test.js 并使用--runInBand 运行:
import { testSuite1, testSuite2 } from './tests'
describe('sequentially run tests', () => {
testSuite1()
testSuite2()
})
【讨论】:
使用串行测试运行器:
npm install jest-serial-runner --save-dev
设置 jest 以使用它,例如在 jest.config.js 中:
module.exports = {
...,
runner: 'jest-serial-runner'
};
您可以使用项目功能将其仅应用于一部分测试。见https://jestjs.io/docs/en/configuration#projects-arraystring--projectconfig
【讨论】:
--testRunner 参数一起使用吗?这仅适用于 CI/CD,我不想在配置中修改我的跑步者。另外,我不是在谈论--runInBand 选项。
复制自https://github.com/facebook/jest/issues/6194#issuecomment-419837314
test.spec.js
import { signuptests } from './signup'
import { logintests } from './login'
describe('Signup', signuptests)
describe('Login', logintests)
signup.js
export const signuptests = () => {
it('Should have login elements', () => {});
it('Should Signup', () => {}});
}
login.js
export const logintests = () => {
it('Should Login', () => {}});
}
【讨论】:
虽然 --runInBand 有效,但它的作用超出了您的需要 - 根据 Jest 的文档:
在当前进程中连续运行所有测试,而不是创建运行测试的子进程的工作池 (...)
通常,Jest 使用一个父调度程序进程运行,该进程将子进程调度为并行有效地运行您的测试的工作人员。 runInBand 似乎通过将所有内容压缩到一个进程中来打破这种架构。
为了保留该核心范例并按顺序运行,您可以使用--maxWorkers 1,它会将同时运行的工作人员的数量限制为 1(从而导致顺序运行):
jest --maxWorkers 1
jest -w 1也可以作为别名使用。
这样做的好处是,不像使用 runInBand 那样采用任何特殊的相同 JS-context-all-around 假设(例如在各种配置/环境中),您会更安全地玩它setup 文件),如果可能的话,这将阻止您在未来使用并行性。
【讨论】:
-runInBand 与 --maxWorkers=1 完全相同,它们是可以互换的。检查代码:github.com/facebook/jest/blob/…
runInBand 时,工人计数被强制为一。它与我解释的所有其他内容完全无关——即流程和 JS 上下文管理,这是答案的核心。
runInBand 的代码,更具体地说,搜索{testRunner}.serial - --maxWorkers=1 与--runInBand 具有完全相同的行为,这使您的答案表面上是错误的。使用一个比另一个更安全(--runInBand 没有什么不安全的)。见:-github.com/facebook/jest/blob/…-github.com/facebook/jest/blob/…
runInBand。当maxWorkers 为 1 时,没有创建工作池。两者的结果是完全相同的代码路径。你错了,拒绝阅读我提供的源代码的直接链接。
是的,您也可以按特定顺序运行所有测试,但通常您的测试应该是独立的,因此我强烈警告不要依赖任何特定顺序。话虽如此,可能有一个有效的案例来控制测试顺序,所以你可以这样做:
在运行 jest 时添加 --runInBand 作为选项,例如在package.json。这将按顺序而不是并行(异步)运行测试。使用--runInBand 可以防止一组测试中的设置/拆卸/清理等问题干扰其他测试:
"scripts": {"test": "jest --runInBand"}
将所有测试放入单独的文件夹(例如__tests__下的单独文件夹,命名为test_suites):
__tests__
test_suites
test1.js
test2.js
在 package.json 中配置 jest 以忽略此 test_suites 文件夹:
"jest": { "testPathIgnorePatterns": ["/test_suites"] }
在__tests__ 下创建一个新文件,例如tests.js - 这是现在唯一实际运行的测试文件。
在tests.js、require 中,按照您要运行它们的顺序排列各个测试文件:
require('./test_suites/test1.js');
require('./test_suites/test2.js');
注意 - 这将导致测试中的afterAll() 在所有 测试完成后运行。从本质上讲,它打破了测试的独立性,应该在非常有限的场景中使用。
【讨论】:
来自开玩笑documentation:
Jest 在执行之前执行测试文件中的所有描述处理程序 任何实际测试。这是进行设置和 在 before* 和 after* 处理程序内部而不是在 描述块。
一旦描述块完成,默认情况下 Jest 按顺序运行所有测试 在收集阶段遇到,等待每个完成并被 在继续之前整理一下。
看看这个笑话网站给出的例子。
【讨论】:
以防万一有人想在 package.json 选项中保留所有 jest 配置。
runInBand 似乎不是有效的配置选项。这意味着您最终可能会得到下面看起来不是 100% 完美的设置。
"scripts": {
"test": "jest --runInBand"
},
...
"jest": {
"verbose": true,
"forceExit": true,
"preset": "ts-jest",
"testURL": "http://localhost/",
"testRegex": "\\.test\\.ts$",
...
}
...
但是,您可以使用 maxWorkers 选项添加 runInBand,如下所示:
"scripts": {
"test": "jest"
},
...
"jest": {
"verbose": true,
"maxWorkers": 1,
"forceExit": true,
"preset": "ts-jest",
"testURL": "http://localhost/",
"testRegex": "\\.test\\.ts$",
...
}
...
【讨论】:
我需要它来处理与常规测试一起的端到端测试,而runInBand 解决方案对我来说还不够。是的:它确保在测试套件/文件中该顺序有效,但文件本身按照 Jest 为并行化而选择的顺序运行,并且不容易控制。如果您需要测试套件本身的稳定顺序,您可以这样做。
所以除了--runInBand,我还做了以下。顺便说一下,我在一个存储库中为此使用了单独的项目。
我的jest.config.js 看起来像这样:
module.exports = {
testSequencer: "./__e2e__/jest/customSequencer.js",
projects: [{
"rootDir": "<rootDir>/__e2e__",
"displayName": "end-to-end",
...
在这里,我明确地将displayName 添加为end-to-end,即
我以后会用。像往常一样,您可以拥有任意数量的项目,但是
我有两个,一个用于普通单元测试,一个用于端到端。
请注意,testSequencer 字段必须是全局的。如果你附上它
对于一个项目,它将被验证,但随后会被默默地忽略。那是一个
使排序适合运行多个项目的开玩笑决定。
testSequencer 字段指向包含此内容的文件。这进口
测试序列器的默认版本,然后对测试进行分区
分成两组,一组用于end-to-end 项目中的测试,而所有的
休息。其余的都委托给继承的序列器,但那些在
端到端集按字母顺序排序,然后连接起来。
const Sequencer = require('@jest/test-sequencer').default;
const isEndToEnd = (test) => {
const contextConfig = test.context.config;
return contextConfig.displayName.name === 'end-to-end';
};
class CustomSequencer extends Sequencer {
sort(tests) {
const copyTests = Array.from(tests);
const normalTests = copyTests.filter((t) => ! isEndToEnd(t));
const endToEndTests = copyTests.filter((t) => isEndToEnd(t));
return super.sort(normalTests).concat(endToEndTests.sort((a, b) => (a.path > b.path ? 1 : -1)));
}
}
module.exports = CustomSequencer;
这个组合运行 Jest 喜欢的所有常规测试,但始终以 alpha 顺序在最后运行端到端测试,从而为我的端到端测试提供额外的稳定性,让用户模型按照他们需要的顺序运行。
【讨论】: