如何 运行 Jest 顺序测试?

How to run Jest tests sequentially?

我正在 运行通过 npm test 进行 Jest 测试。 Jest 运行s 默认并行测试。有什么方法可以按顺序进行测试 运行 吗?

我有一些调用依赖于更改当前工作目录的第三方代码的测试。

CLI options are documented 也可以通过 运行 命令 jest --help.

访问

您会看到您正在寻找的选项:--runInBand

我仍然熟悉 Jest,但似乎同步描述块 运行 而异步测试块 运行。我 运行 在一个看起来像这样的外部描述中使用多个描述块:

describe
    describe
        test1
        test2

    describe
        test3

在这种情况下,test3 不会 运行 直到 test2 完成,因为 test3 位于包含 [=12 的描述块之后的描述块中=].

它对我有用,确保按顺序 运行 很好地分离模块测试:

1) 将测试保存在单独的文件中,但没有 spec/test 命名。

|__testsToRunSequentially.test.js
|__tests
   |__testSuite1.js
   |__testSuite2.js
   |__index.js

2) 带有测试套件的文件也应该如下所示 (testSuite1.js):

export const testSuite1 = () => describe(/*your suite inside*/)

3) 使用 --runInBand:

将它们导入 testToRunSequentially.test.js 和 运行
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 的文档:

Run all tests serially in the current process, rather than creating a worker pool of child processes that run tests (...)

通常,Jest 运行 使用一个父调度程序进程,该进程将子进程作为有效地并行调度 运行 您的测试的工作人员。 runInBand 似乎通过 c运行 将所有内容集成到一个进程中来打破该体系结构。

为了保留该核心范例和 运行 顺序,您可以使用 --maxWorkers 1,这将简单地将并发 运行ning worker 的数量限制为 1(因此导致按顺序 运行):

jest --maxWorkers 1

jest -w 1 also works, as an alias.

这样做的好处是,您可以通过 而不是 runInBand 那样采用任何特殊的 same-JS-context-all-around 假设来更安全地使用它(例如,在各种配置/环境设置文件中),如果可能的话,这会阻止您将来采用并行性。

是的,您还可以 运行 按特定顺序进行所有测试,但通常您的测试应该是独立的,因此我强烈警告不要依赖任何特定顺序。话虽如此,控制测试顺序可能有一个有效的案例,所以你可以这样做:

  • 添加--runInBand作为运行开玩笑时的选项,例如在 package.json。这将 运行 按顺序而不是并行(异步)进行测试。使用 --runInBand 可以防止一组测试中的 setup/teardown/cleanup 之类的问题干扰其他测试:

  • "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() 一旦 all 测试具有完全的。本质上它打破了测试的独立性,应该在非常有限的场景中使用。

来自笑话 documentation:

Jest executes all describe handlers in a test file before it executes any of the actual tests. This is another reason to do setup and teardown inside before* and after* handlers rather than inside the describe blocks.

Once the describe blocks are complete, by default Jest runs all the tests serially in the order they were encountered in the collection phase, waiting for each to finish and be tidied up before moving on.

看看jest网站给的例子

以防万一有人想在 package.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 解决方案对我来说还不够。是的:它确保在测试 suites/files 中该顺序有效,但文件本身 运行 的顺序基本上是由 Jest 并行化选择的,并且不容易控制。如果您需要测试套件本身的稳定顺序,这就是您可以做到的。

所以 除了 --runInBand,我还做了以下事情。顺便说一句,我在一个存储库中为此使用单独的项目。

  1. 我的 jest.config.js 看起来像这样:

     module.exports = {
       testSequencer: "./__e2e__/jest/customSequencer.js",
       projects: [{
         "rootDir": "<rootDir>/__e2e__",
         "displayName": "end-to-end",
         ...
    

    这里我明确的把displayName加成了end-to-end,这样 我以后会用的。像往常一样,您可以拥有任意数量的项目,但是 我有两个,一个用于普通单元测试,一个用于端到端。

    请注意 testSequencer 字段必须是全局的。如果你附上它 对于一个项目,它会被验证但随后被默默地忽略。那是一个 让 运行 宁多个项目的排序很好的决定。

  2. 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 的新手,并且正在寻找一个完整的 step-by-step 关于如何制作特定测试文件的示例总是 运行 首先或最后,这里是:

  1. 在您喜欢的任何路径中创建一个名为“testSequencer.js”的文件。
  2. 将下面的代码粘贴到该文件中。
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 (auth_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;
  1. 在您的 package.json 玩笑配置中将“maxWorkers”选项设置为“true”。此外,将“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
  }
}
  1. 运行 npm test 并观察每个测试文件将 运行 一个接一个,每个完成后。你牺牲了一些时间,但这样保证了秩序。

好处:您还可以按字母顺序、文件夹名称等对测试文件进行排序。只需根据您的喜好修改“testSequencer.js”文件,然后 return 一个与“测试”数组,这是您主要“排序”功能的参数,您会很好。