【问题标题】:How to run Jest tests sequentially?如何按顺序运行 Jest 测试?
【发布时间】:2015-12-21 11:40:52
【问题描述】:

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

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

【问题讨论】:

    标签: jestjs


    【解决方案1】:

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

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

    【讨论】:

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

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

    describe
        describe
            test1
            test2
    
        describe
            test3
    

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

    【讨论】:

    • 也许它仍然会并行运行。
    • 这很棒。可以先检查缺少环境变量的行为,然后设置变量并进行进一步测试。
    • IMO 这应该是公认的答案。比处理 CLI 选项或定义序列器更容易。
    • 这对我测试有状态的 WebSocket 服务器(连接、登录、注销)非常有效,显然它必须以正确的顺序运行。不过,外部的describe 不是必需的。
    【解决方案3】:

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

    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 运行,因为您已经有两个测试套件。子测试套件按顺序执行。
    【解决方案4】:

    使用串行测试运行器:

    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 选项。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      虽然 --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/…
      • 请考虑删除或编辑您的答案,因为它会误导人们。
      • 老兄,我给你提供了确切的来源,你给了我文档。在内部将 max workers 设置为 1 会转换为 runInBand。当maxWorkers 为 1 时,没有创建工作池。两者的结果是完全相同的代码路径。你错了,拒绝阅读我提供的源代码的直接链接。
      【解决方案7】:

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

      • 在运行 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.jsrequire 中,按照您要运行它们的顺序排列各个测试文件:

        require('./test_suites/test1.js');

        require('./test_suites/test2.js');

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

      【讨论】:

        【解决方案8】:

        来自开玩笑documentation

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

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

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

        【讨论】:

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

        以防万一有人想在 package.json 选项中保留所有 jest 配置。

        runInBand 似乎不是有效的配置选项。这意味着您最终可能会得到下面看起来不是 100% 完美的设置。

        "scripts": {
            "test": "jest  --runInBand"
        },
        ...
        "jest": {
            "verbose": true,
            "forceExit": true,
            "preset": "ts-jest",
            "testURL": "http://localhost/",
            "testRegex": "\\.test\\.ts$",
            ...
          }
        ...
        

        但是,您可以使用 ma​​xWorkers 选项添加 runInBand,如下所示:

          "scripts": {
                "test": "jest"
            },
            ...
            "jest": {
                "verbose": true,
                "maxWorkers": 1,
                "forceExit": true,
                "preset": "ts-jest",
                "testURL": "http://localhost/",
                "testRegex": "\\.test\\.ts$",
                ...
              }
            ...
        

        【讨论】:

          【解决方案10】:

          我需要它来处理与常规测试一起的端到端测试,而runInBand 解决方案对我来说还不够。是的:它确保在测试套件/文件中该顺序有效,但文件本身按照 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 顺序在最后运行端到端测试,从而为我的端到端测试提供额外的稳定性,让用户模型按照他们需要的顺序运行。

          【讨论】:

          猜你喜欢
          • 2018-08-21
          • 1970-01-01
          • 1970-01-01
          • 2015-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多