javascript - Jest 是否异步运行用 describe() 定义的测试套件?

标签 javascript angularjs jestjs puppeteer

问题总结:我正在编写几个测试套件(使用 Jest 和 Puppeteer)来自动测试我的 AngularJS 应用程序的 index.html 页面。不幸的是,我在运行测试时看到一些奇怪的行为,我认为这与 Jest 运行我的各种测试套件的顺序有关。

背景:我使用 Jest (v24.8.0) 作为我的测试框架。我正在使用 Puppeteer (v1.19.0) 启动并控制 Chromium 浏览器以执行我的测试。

我的代码:

<!-- index.html -->
<div ng-app="myApp" ng-controller="myCtrl as ctrl">
    <form name="form1">
        <md-input-container>
            <label class="md-required">Name</label>
            <input ng-model="ctrl.name1"></input>
        </md-input-container>
        <md-dialog-actions>
            <button class="md-primary md-button" ng-transclude type="submit">Submit</button>
        </md-dialog-actions>
    </form>
    <form name="form2">
        <md-input-container>
            <label class="md-required">Name</label>
            <input ng-model="ctrl.name2"></input>
        </md-input-container>
        <md-dialog-actions>
            <button class="md-primary md-button" ng-transclude type="submit">Submit</button>
        </md-dialog-actions>
    </form>
</div> 
// index.spec.js
const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();
    await page.goto('https://my-site.com');

    describe('form 1', async () => {
        test('populate form 1', async () => {
            let formSelector = 'form[name="form1"]';
            await page.waitForSelector(formSelector+' input', {timeout: 3000});
            await page.click(formSelector+' input');
            await page.keyboard.type('casey');
            let submitButtonSelector = 'form[name="form1"] button[type="submit"]';
            await page.click(submitButtonSelector);
        });
    });
    describe('form 2', async () => {
        test('populate form 2', async () => {
            let formSelector = 'form[name="form2"]';
            await page.waitForSelector(formSelector+' input', {timeout: 3000});
            await page.click(formSelector+' input');
            await page.keyboard.type('jackie');
            let submitButtonSelector = 'form[name="form2"] button[type="submit"]';
            await page.click(submitButtonSelector);
        });
    });
    await browser.close();
})();

测试行为: 有时 当我运行 npm test看来我的两个测试套件,'form1''form2' (我用 describe 定义)正在并行运行(虽然我知道这在 Javascript 中是不可能的,所以我假设 Jest 异步运行不同的测试套件)。无论哪种方式,当我在非 headless 模式下运行测试时,我都可以看到 form1的名称输入填充为 'jackie' , 即使它应该是 'casey' .在那之后,form2永远不会填写(即使我的第二个测试套件应该这样做)并且测试完成,之后 Jest 通知我 'populate form 2'失败了。同样,这不会在我运行测试时每次 发生,因此您可能无法重现我的问题。

我的问题:

  1. Jest 是否并行/异步运行测试套件? 注意:我不是在谈论用 test 定义的个别测试在测试套件中,我知道如果我将 async 传递给它们,它们将异步运行。功能。

  2. 如果 Jest 确实异步运行测试套件,我该如何禁用它?或者更好的是,为不同的测试套件提供不同的智能/传统/最佳 browser实例以便它们在完全独立的窗口中运行?是否有任何其他方法可确保测试套件单独和/或同步运行?

  3. 如果 Jest 不异步运行测试套件,那么您认为我为什么会看到这种行为?

我问是因为我想找到一种方法来确保我所有的测试始终通过,而不是仅仅在某些时候通过。从长远来看,这将使确定我在开发过程中所做的更改是否破坏了任何东西变得更加容易。

提前感谢所有 Jest/Puppeteer 黑客!

最佳答案

默认情况下,Jest 根据 max workers 在每个文件中同时运行测试。 , 但是 runs all describe and tests blocks serially within a file .

如果您希望所有文件连续运行,请使用 run in band ,这将删除工作人员池。

不过,我推荐重构,你可以嵌套describe block

// instead of IIFE, nest describes for better parsing for jest and readability
describe('forms', async () => {
    const browser = await puppeteer.launch({headless: false});

    describe('form 1', () => {
        test('populate form 1', async () => {
            // make every test independent of the other to avoid leaky scenarios
            const page = await browser.newPage();
            await page.goto('https://my-site.com');
            let formSelector = 'form[name="form1"]';
            await page.waitForSelector(formSelector+' input', {timeout: 3000});
            await page.click(formSelector+' input');
            await page.keyboard.type('casey');
            let submitButtonSelector = 'form[name="form1"] button[type="submit"]';
            await page.click(submitButtonSelector);
        });
    });
    describe('form 2', () => {
        test('populate form 2', async () => {
            const page = await browser.newPage();
            await page.goto('https://my-site.com');
            let formSelector = 'form[name="form2"]';
            await page.waitForSelector(formSelector+' input', {timeout: 3000});
            await page.click(formSelector+' input');
            await page.keyboard.type('jackie');
            let submitButtonSelector = 'form[name="form2"] button[type="submit"]';
            await page.click(submitButtonSelector);
        });
    });

    await browser.close();
})

更新

在 NodeJS 中你可以 spawn processes ,在jest的情况下,每个进程都是一个节点实例,它们通过标准IO进行通信。您可以通过 CLI 选项告诉 jest 有多少生成,但是,由于 NodeJS 实例是重量级的,并且 spawn/sync 可能比实际运行更昂贵在乐队或少数 worker 。

此外,对于它们的运行方式没有任何保证,如果您想生成 10 个进程,您的操作系统可能会将所有进程调度到同一个 CPU 线程,并且它们将连续运行。

关于javascript - Jest 是否异步运行用 describe() 定义的测试套件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57368025/

相关文章:

javascript - 使用 Angularjs 和 UI Router 的 event.preventDefault() 删除浏览器历史记录

javascript - 带 Prop 的 Jest 快照

javascript 从桌面 : dragenter/dragleave triggers uncorrectly 拖动文件

javascript - 配置服务(通过其提供者)以使用另一服务

javascript - 如何在javascript按钮中隐藏标题栏和工具栏

reactjs - global.location 在 Jest 测试中不起作用

node.js - 使用 Supertest 进行测试时在 header 部分设置 Bearer Token

javascript - 引用对象中的其他Key

javascript - url-to-image 渲染我尝试的每个 URL,除了我需要的 URL

angularjs - 从 POST 返回 ID