我正在通过npm测试运行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)将它们导入testtorunsequential .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', () => {}});
}

是的,您还可以以特定的顺序运行所有测试,尽管通常您的测试应该是独立的,所以我强烈警告不要依赖任何特定的顺序。说到这里,可能有一个控制测试顺序的有效案例,所以你可以这样做:

Add --runInBand as an option when running jest, e.g. in package.json. This will run tests in sequence rather than in parallel (asynchronously). Using --runInBand can prevent issues like setup/teardown/cleanup in one set of tests intefering with other tests: "scripts": {"test": "jest --runInBand"} Put all tests into separate folder (e.g. a separate folder under __tests__, named test_suites): __tests__ test_suites test1.js test2.js Configure jest in package.json to ignore this test_suites folder: "jest": { "testPathIgnorePatterns": ["/test_suites"] } Create a new file under __tests__ e.g. tests.js - this is now the only test file that will actually run. In tests.js, require the individual test files in the order that you want to run them: require('./test_suites/test1.js'); require('./test_suites/test2.js');

注意——这将导致测试中的afterAll()在所有测试完成后运行。从本质上讲,它破坏了测试的独立性,应该在非常有限的场景中使用。


来自Jest文档:

Jest在执行之前执行测试文件中的所有描述处理程序 任何实际的测试。这是另一个建立和的原因 在*和*处理程序之前和之后拆除,而不是在 描述模块。

一旦描述块完成,默认情况下 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为并行化选择的顺序运行,并且不容易控制。如果您需要测试套件本身的稳定顺序,那么您可以这样做。

除了——runInBand之外,我做了以下操作。顺便说一下,我在一个存储库中使用了单独的项目。

My jest.config.js looks like this: module.exports = { testSequencer: "./__e2e__/jest/customSequencer.js", projects: [{ "rootDir": "<rootDir>/__e2e__", "displayName": "end-to-end", ... Here, I explicitly added the displayName to be end-to-end, which I'll use later. You can have as many projects as you like, as usual, but I have two, one for normal unit tests, and one for end-to-end. Note that the testSequencer field has to be global. If you attach it to a project, it'll be validated but then ignored silently. That's a Jest decision to make sequencing nice for running multiple projects. The testSequencer field points to a file containing this. This imports a default version of the test sequencer, and then partitions the tests into two sets, one for the tests in the end-to-end project, and all the rest. All the rest are delegated to the inherited sequencer, but those in the end to end set are sorted alphabetically and then concatenated. 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的新手,正在寻找一个完整的,循序渐进的例子,如何让一个特定的测试文件总是在第一个或最后一个运行,下面是:

在你想要的任何路径上创建一个名为“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;

        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”选项设置为“true”。Json笑话配置。另外,将“testSequencer”选项设置为新创建的“testSequencer.js”文件的路径。

{
  "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
  }
}

运行npm test并观察每个测试文件将在每个测试完成后逐个运行。你牺牲了一些时间,但你这样做保证了订单。

额外的好处:你还可以按字母顺序、文件夹名等顺序排列测试文件。只需根据自己的喜好修改“testsequcer .js”文件,并返回一个与“tests”数组格式相同的数组,该数组是主“sort”函数的参数,这样就可以了。


Jest按照在收集阶段遇到的顺序连续运行所有测试

你可以利用它并创建特殊的测试文件alltests.ordered-test.js:

import './first-test'
import './second-test'
// etc.

并添加一个带有testMatch的笑话配置,它将使用该文件名运行测试。

这将按该顺序加载每个文件,从而以相同的顺序执行它们。