关于删除前端测试中的 wait 的一些分享

最近学习了如何用 cypress 写前端的测试,在写测试的过程中,发现了一个经常可以见到的 wait 方法,起初我也不以为然,甚至对它产生了友好的感觉,一旦 CI 报错我就会尝试用 wait 来解决它,尽管实用,它也并不会影响测试的正常运行,但是在小伙伴告诉我,它不应该被这样用的时候,我重新去阅读了官方文档,官方文档写的很清楚,我们几乎不需要等待任何的时间在我们的测试中。并给出了一些规范的例子,然后我就开始将我测试中的wait 一个一个去除掉。在这里我分享一下我在删除那些测试中的 wait 时遇到的一些问题和技巧。


我发现在一些测试中用了许多 wait,但其实这些 wait 并没有起到一点作用,(:直接删除掉就好了,并且不影响 CI 检查),我将列出一些列子与方法来讲解它们:

  1. 那些通常出现在 click 之后的 wait。并不是每个点击之后都需要暂停一下的,通常,只有在点击按钮后需要解析部分资源,以及点击按钮后产生的新元素等可能需要用 timeout 来短暂的等待它们出现。同样也可以使用 should 来进行判断。像点击下一页,点击创建,点击提交这些点击并不需要等待,但是点击编辑,点击按钮产生的新元素时,就会需要用 timeout 或者 should 来使测试在 CI 中更稳定一些。在 cypress 中,很多方法都支持 timeout ,当我们想延迟点击按钮时,我们可以为 click 加上 timeout 属性,来延迟点击它,当我们希望在点击后等待时,我们可以在点击后出现的元素中使用加上 get + should 的方法来确保它们出现后再往后进行,当然 get 同样支持 timeout 属性。

注意:当 click 具有 force 属性时,timeout 将失效。

  1. 那些用来等待解析资源的 wait。我发现在写编辑测试的时候,点击编辑按钮后,我们可以使用 should 判断一些元素是否正常出现,而不用使用 wait 来等待。同样对于等待 URL 解析的 wait 我们可以用 interceptwait 搭配来等待域名的解析,像这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
it('should set a accessible URL', function () {
cy.visit('/');
cy.get(selector.avatar).invoke('show').click('center');
cy.contains('Settings').click();
cy.url().should('contains', '/settings');
cy.get(selector.grafanaURL).clear().type(data.validURL);
cy.contains('Submit').click();

cy.get(selector.notificationMessage).should('contain', data.updateSuccessfully);
cy.intercept(data.validURL).as(data.fetchURL);
cy.wait(data.fetch);
cy.get(selector.pageContainer).children().should('contain', 'Dashboard');
});

这里分享一个小技巧,我们可以使用在点击某个跳转之后,使用 get 获取任一元素,然后加一个 click 然后用 should 来判断它是否出现,就可以确保正确的访问到最新的 dom 元素,至于为什么用 click 是因为在对 dom 进行操作时,因为 Cypress 运行的速度非常快,如果只是寻找某个节点的信息,它不一定找到的是最新的 dom 节点,如果对旧 dom 进一步进行操作那就不对了。所以当找到的 dom 元素不是最新的时候,我们点击它之后,再用 should 方法来进行判断它是否是我们寻找的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
it('should edit route with cors form no allow_origins_by_regex configured', function () {
cy.visit('/');
cy.contains('Route').click();
cy.get(selector.name).clear().type('routeName');
cy.contains('Search').click();
cy.contains('routeName').siblings().contains('Configure').click();
cy.get(selector.name).should('have.value','routeName');
cy.contains('Next').click();
cy.contains('Next').click();

// config cors plugin
cy.contains('cors').parents(selector.pluginCardBordered).within(() => {
cy.get('button').click({
force: true
});
});
  1. 路由跳转后的 wait。通常首次点击进入到某个页面后是不需要等待的,但是我在删除部分 wait 的时候,偶尔会遇到 CI 报错的情况,这种时候我会用三种方法来处理:
  • 通常页面中会有一个刷新的按钮,点击它使页面刷新。
  • click 之后使用 reload,使页面重新加载。
  • 使用 get 获取元素,用 should 判断它正常出现。

最后,以上便是我在删除 wait 时的分享,如果有我理解不对的地方,欢迎大家为我提出建议,感谢大家。