ChatGPT解决这个技术问题 Extra ChatGPT

如何按顺序运行 Jest 测试?

我正在通过 npm test 运行 Jest 测试。 Jest 默认并行运行测试。有没有办法让测试按顺序运行?

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


m
mikemaccana

CLI options are documented,也可以通过运行命令 jest --help 访问。

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


非常感谢!是npm test --runInBand吗?题外话:不知道“乐队”这个名字是从哪里来的。 --runSequentially 可能更有意义:)
@MartinKonicek npm test -- --runInBand 是正确的。
不幸的是,无法控制执行顺序的事实使得 Jest 对于集成测试几乎毫无用处。
@Evan您需要按特定顺序运行测试的事实是一种气味。
@NicoVanBelle 这只是您为足够复杂的有状态系统进行真正的端到端测试所付出的代价。我对替代方案持开放态度,但我还没有看到一个解决方案,它既不涉及天真地交换堆栈的关键部分,也不涉及测试之间的数据库重置速度过慢。并不意味着 Jest 是一个糟糕的工具,只是这种特殊测试的错误工具。
S
SuperCodeBrah

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

describe
    describe
        test1
        test2

    describe
        test3

在这种情况下,在 test2 完成之前,test3 不会运行,因为 test3 位于包含 test2 的描述块之后的描述块中。


也许它仍然会并行运行。
这很棒。可以首先检查缺少环境变量的行为,然后设置变量并进行进一步的测试。
IMO 这应该是公认的答案。比处理 CLI 选项或定义序列器更容易。
这对我测试有状态的 WebSocket 服务器(连接、登录、注销)非常有效,显然它必须以正确的顺序运行。但是,外部 describe 不是必需的。
这几乎看起来像是不安全的实现细节。
k
kmnowak

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

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()
})

您不需要使用 --runInBand 运行,因为您已经有两个测试套件。子测试套件按顺序执行。
J
Joachim Lous

使用串行测试运行器:

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


您可以使用项目功能将其仅用于一部分测试。,如何?
@Nux Jest 中的“项目”配置设置允许您有选择地将其他配置设置应用于特定的测试集。答案更新为文档和示例的链接。
知道如何将它与 --testRunner 参数一起使用吗?这仅适用于 CI/CD,我不想在配置中修改我的跑步者。另外,我不是在谈论 --runInBand 选项。
M
Mor Shemesh

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', () => {}});
}

S
Stuart Watt

我需要它来处理与常规测试一起的端到端测试,而 runInBand 解决方案对我来说还不够。是的:它确保在测试套件/文件中该顺序有效,但文件本身按照 Jest 为并行化而选择的顺序运行,并且不容易控制。如果您需要测试套件本身的稳定顺序,这就是您可以做到的。

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

我的 jest.config.js 看起来像这样: module.exports = { testSequencer: "./__e2e__/jest/customSequencer.js", projects: [{ "rootDir": "/__e2e__", "displayName": " end-to-end", ... 在这里,我明确地将 displayName 添加为 end-to-end,稍后我将使用它。像往常一样,您可以拥有任意数量的项目,但我有两个,一个用于普通单元测试,一个用于端到端。请注意, testSequencer 字段必须是全局的。如果您将其附加到项目中,它将被验证但随后会被忽略。这是一个开玩笑的决定,让排序适合运行多个项目。 testSequencer 字段指向一个包含它的文件。这会导入测试序列器的默认版本,然后将测试分成两组,一组用于端到端项目中的测试,其余的都用于测试。其余的都委托给继承的排序器,但端到端集中的排序器按字母顺序排序,然后连接起来。 const Sequencer = require('@jest/test-sequencer').default; const isEndToEnd = (test) => { const contextConfig = test.context.config; return contextConfig.displayName.name === 'end-to-end'; };类 CustomSequencer 扩展 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 的文档有一个很好的例子:jestjs.io/docs/configuration#testsequencer-string
D
Dharman

以防万一有人想在 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$",
        ...
      }
    ...

C
Chris Halcrow

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

在运行 jest 时添加 --runInBand 作为选项,例如在 package.json 中。这将按顺序而不是并行(异步)运行测试。使用 --runInBand 可以防止一组测试中的设置/拆卸/清理等问题干扰其他测试:

“脚本”:{“测试”:“开玩笑--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('./test_suites/test1.js');要求('./test_suites/test2.js');

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


O
Onur Çevik

如果您是 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 (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;

在您的 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
  }
}

运行 npm test 并观察每个测试文件将在每个完成后一个接一个地运行。您牺牲了一些时间,但您以这种方式保证了订单。

奖励:您还可以按字母顺序、文件夹名称等对测试文件进行排序。只需根据您的偏好修改“testSequencer.js”文件,并返回一个与“tests”数组格式相同的数组,这是您的参数主要的“排序”功能,你会很好。


B
BigMan73

从笑话 documentation

Jest 在执行任何实际测试之前执行测试文件中的所有描述处理程序。这是在 before* 和 after* 处理程序内部而不是在 describe 块内部进行设置和拆卸的另一个原因。

一旦描述块完成,默认情况下,Jest 按照它们在收集阶段遇到的顺序依次运行所有测试,等待每个测试完成并在继续之前进行整理。

看看这个笑话网站给出的例子。


当您有不同的测试文件具有不同的 before* 和 after* 时,也会出现问题。想象一下,您使用一个真实的数据库来针对它运行测试。如果你并行运行它们,就会有冲突。这实际上取决于您设置的测试类型。