我正在通过npm test
运行Jest测试。Jest默认情况下并行运行测试。是否有办法使测试按顺序运行?
我有一些测试调用依赖于更改当前工作目录的第三方代码。
CLI选项有文档记录,也可以通过运行命令jest --help
来访问。
您将看到您正在寻找的选项:--runInBand
.
我仍然熟悉Jest,但似乎描述块同步运行,而测试块异步运行。我在外部描述中运行多个描述块,看起来像这样:
describe
describe
test1
test2
describe
test3
在这种情况下,test3
不会运行,直到test2
完成,因为test3
在包含test2
的描述块之后的描述块中。
它为我工作,确保顺序运行良好地分离到模块测试:
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
复制自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选择的顺序运行,这是为了并行化,而且不容易控制。如果您需要测试套件本身的稳定顺序,您可以这样做。
所以除了--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顺序在最后运行端到端测试,为用户模型提供了额外的端到端测试稳定性。
以防有人想在包中保留所有jest配置。json 选项。
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时的选项,例如在package.json
中。这将按顺序运行测试,而不是并行(异步)运行测试。使用--runInBand
可以防止一组测试中的设置/拆除/清理等问题干扰其他测试: -
"scripts": {"test": "jest --runInBand"}
-
将所有测试放到单独的文件夹中(例如
__tests__
下的单独文件夹,命名为test_suites
):__tests__
test_suites
test1.js
test2.js
-
配置jest在
package.json
忽略这个test_suites
文件夹:"jest": { "testPathIgnorePatterns": ["/test_suites"] }
-
在
__tests__
下创建一个新文件,例如tests.js
-这是现在唯一可以实际运行的测试文件。 -
在
tests.js
,require
中,按您想要运行的顺序排列单个测试文件:require('./test_suites/test1.js');
require('./test_suites/test2.js');
注意—这将导致在所有测试完成后运行测试中的afterAll()
。从本质上讲,它破坏了测试的独立性,应该在非常有限的场景中使用。
如果您是Jest的新手,并且正在寻找一个关于如何使特定的测试文件总是首先或最后运行的完整的,分步的示例,下面是它:
- 创建一个名为"testSequencer.js"
- 将下面的代码粘贴到该文件中。
const TestSequencer = require('@jest/test-sequencer').default;
const path = require('path');
class CustomSequencer extends TestSequencer {
sort(tests) {
const target_test_path = path.join(__dirname, 'target.test.js');
const target_test_index = tests.findIndex(t => t.path === target_test_path);
if (target_test_index == -1) {
return tests;
}
const target_test = tests[target_test_index];
const ordered_tests = tests.slice();
ordered_tests.splice(target_test_index, 1);
ordered_tests.push(target_test); // adds to the tail
// ordered_tests.unshift(target_test); // adds to the head
return ordered_tests;
}
}
module.exports = CustomSequencer;
- 设置"maxWorkers"选项为"1"在你的包裹里。Json jest配置。另外,设置testSequencer"选项作为新创建的" testsequence .js"文件的路径。
- 运行npm test,观察每个测试文件都将一个接一个地运行,每个文件完成后。你牺牲了一些时间,但这样你保证了订单。
{
"name": "myApp",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "jest"
},
"author": "Company",
"license": "MIT",
"dependencies": {
...
},
"devDependencies": {
"jest": "^27.5.1",
...
},
"jest": {
"testSequencer": "./testSequencer.js",
"maxWorkers": 1
}
}
奖励:您还可以按字母顺序,按文件夹名称等对测试文件进行排序。只需修改" testsequence .js"文件,并返回与"tests"格式相同的数组。数组,它是主"sort"的参数。功能,你会很好。
来自Jest文档:
Jest在执行之前执行测试文件中的所有描述处理程序任何实际的测试。这是进行setup和的另一个原因在before*和after*处理程序内拆,而不是在描述块。
一旦描述块完成,默认情况下Jest按照顺序依次运行所有的测试在收集阶段遇到了,等待着每一次的完成和被整理好再继续。
看一下笑话网站给出的例子。
Jest按照它们在收集阶段遇到的顺序依次运行所有测试
您可以利用它并创建特殊的测试文件alltests.ordered-test.js
:
import './first-test'
import './second-test'
// etc.
并添加一个带有testMatch
的jest配置,该配置将使用该文件名运行测试。
将按顺序加载每个文件,从而以相同的顺序执行它们。
我尝试了上面提到的几种方法,但似乎都不起作用。可能是因为我没有得到正确的构型。下面是对我有用的
- 我将script.sh中的执行顺序设置如下
# ./script.sh
npm test pretest
node dosomething.js # this call will take a while to finish
npm test posttest
- chmod 755 script.sh
- 。/script.sh
基本上,前测和后测是测试的名称。它们中的每一个在__ tests __目录下都有一个相应的测试文件名(pretest.test.js和posttest.test.js)。