Docker中Puppeteer / Jest测试中的竞争条件

时间:2019-04-24 18:36:27

标签: docker jestjs puppeteer race-condition

我用jest&puppeteer编写了一个大型测试,该测试在我的应用程序中完成了很多工作。

当我在本地运行测试时-一切都会通过99%的时间。

当我在Docker中运行测试时-测试在多个位置不一致地失败。几乎每次我运行测试时,它通常在等待选择器加载时失败。

不幸的是,我无法在这里共享我的代码,但是我可以根据我已经完成的研究表明我为减轻故障所做的工作。

  1. 在发生导航之后或声明之前放置waitFor(< x ms>)个呼叫
  2. 按照puppeteer docs中针对点击事件的建议实施Promise.all模式。像这样:
async singleClickElement(selector, page) {
    try {
      await Promise.all([
        page.waitForSelector(selector),
        page.click(selector)
      ]);
    } catch (error) {
      console.error(error)
    }
  }
  1. 处理sloMo设置(考虑到我们的默认CSS转换为.4s,似乎17对我来说是最成功的数字)

  2. 使用screenshots在测试失败的地方拍摄之前/之后的照片

我忘记提及的一些修改

  1. 我的参数--forceExit --runInBand --detectOpenHandles

  2. 我的超时时间增加到最小jest.setTimeout(60000)

  3. 浏览器参数'--window-size=2560,1080', '--no-sandbox', '--disable-setuid-sandbox', '--enable-logging=stderr', '--v=1'

我没有任何想法,正在寻找有关如何在运行UI测试时减轻Docker中的竞争条件的建议。请随时提出任何您认为可能对我有帮助的建议。谢谢:D

1 个答案:

答案 0 :(得分:0)

经过数月的反复试验,我认为我发现了一些在Docker中运行Jest和Puppeteer的好方法,几乎​​没有失败。

解决方案1:加载页面/组件时等待HTTP响应

Puppeteer具有waitForResponse功能,该功能允许浏览器等待某些响应从服务器返回。在Chrome开发者工具中,查看Network并重新加载您正在浏览的页面并等待响应。

示例:假设我正在加载某些页面,并且正在等待服务器的响应,其中包含有关品牌阵列的一些信息。当我导航到该页面时,我会呼叫

await page.waitForResponse(res => res.url().includes('brands'));

,只有在收到此回复后,我才能继续进行测试。我发现对于其他所有方法来说,这种方法都很安静。

注意:每次重新加载页面时,您的响应可能会以差异间隔出现。举例来说,我的品牌响应速度最快为300毫秒,最慢为900毫秒。 尝试查找来自服务器的数据响应或最常见的最后响应(重新加载10次并观看)

Example of server response in chrome

解决方案2:继续之前检查某些元素的属性

比方说,您的页面将首先加载一个按钮。单击该按钮后,经过0.5秒的短暂过渡后,另一个按钮将出现。 您可以在继续操作之前检查按钮的文本内容

.$eval docs

const saveBtn = await page.$eval('.btn-selector', btn => btn.textContent);
        if (saveBtn.includes('Save')) {
    ...
    }

您还可以单击下拉菜单中选定的下拉列表值

.$ docs

        const brandsSelector = await page.$('select:nth-child(1)');
        const brandsSelectedValue = await page.evaluate(brandsSelector => brandsSelector.options[brandsSelector.selectedIndex].value, brandsSelector);

解决方案3:长时间waitFor通话

有时候上述两种解决方案还不够,而克服困难的唯一方法是调用长waitFor

await page.waitFor(3000);

我通常会尝试避免这些情况,但是有时这是使我的测试通过并在Docker中的分级测试服务器上正常运行的唯一方法。

解决方案#4:使用visible时的waitForSelector属性

有时waitForSelector函数之类的简单事物可能会被忽略,因为它们是如此明显,但此函数却带有一个options对象,您可以将其传递给它

await page.waitForSelector('.selector', {visible: true});

这将等待页面中的某些元素首先可见,然后再对其进行其他操作。

解决方案5:检查云提供商的负载

例如,如果您使用的是AWS,请确保您的实例具有足够高的请求容量,可以在每个时间段内发出请求。我的分阶段测试崩溃了,直到最大程度地提高AWS负载以每秒接收更多请求,这使得一些间歇性故障得以缓解。

解决方案6 :(显然)一起使用所有这些解决方案

在差异环境(尤其是分段服务器)中进行测试时,好运的端到端测试可能会很痛苦。