你不知道的Cypress系列(5) -- "眼瞎"的TestRunner​

iTesting

共 3843字,需浏览 8分钟

 · 2021-03-20

iTesting,爱测试,爱分享



我的新书前端自动化测试框架Cypress从入门到精通出版啦!


自从我的新书<前端自动化测试框架 -- Cypress从入门到精通>上市以来,这本书受到了大量同学热情的追捧和讨论。在跟同学们的交流中,我也了解到, 原来除了国外优秀的公司(例如Adobe, 迪士尼,AutoDesk等等), 国内也有很多公司在尝试使用Cypress提升测试效率。而在Cypress中国群内、在公众号iTesting里,我每天都能看到大量关于Cypress的使用讨论和私下问询。这让我感到无比荣幸。(买了书的同学们,公众号回复你的微信号,拉你到Cypress中国群)。


今天是你不知道的Cypress系列(5) -- "眼瞎"的TestRunner


01

TestRunner是什么

关于TestRunner, 我想大家都已经非常熟悉了。在我的的书中也有其各个用法的专门介绍,这里不再赘述。

仅再次列下其定义:

TestRunner是一个独特的测试运行器。Cypress的所有命令通过它运行。通过TestRunner你可以观测到, 在某一个时刻:1. 哪些命令在执行。2. 这些命令在执行时,你的应用程序处于什么状态。

Cypress八大特性里的时间穿梭能力,和可调试性能力,其实就是通过TestRunner来实现的。


02

Test Runner两种运行模式


Cypress有两种运行方式,分别是交互性运行(Interaction Mode),和无头(Headless Mode)运行。


区别一个是测试运行时你可以看到浏览器启动、执行测试。另一个是没有浏览器界面,你看不到运行过程。


无论是哪种方式运行,大家记得Cypress 是通过它内置的Test Runner来运行你的测试用例的就行。



03

什么, TestRunner也会“瞎”?!


没想到吧?刚开始我也是拒绝相信的。直到我发现我的测试用例还是会出现不稳定、随机失败的现象(Flaky Test)。怪了!不是说用了Cypress之后就不会有这种问题了么?于是我就寻仙访药啊,终于,找到了原因所在。先给大家看一个例子:

describe('iTesting Demo', () => {  it('欢迎关注iTesting', () => {    cy.visit('/?delay=500')    cy.get('.loading').should('be.visible')    cy.get('.loading').should('not.be.visible')    cy.get('li.todo').should('have.length', 2)  })})

这是Cypress官网的一个用例,这个测试第一次成功,再次运行失败了。特别是你把它集成到CI上的时候,你大概率会看到这种失败。


为什么会这样呢?


Test Runner "瞎"了!


04

TestRunner为什么会“瞎”


我们知道,修复一个Bug的最好手段就是稳定重现它。怎么重现呢? 先设定一个小目标,先运行它个20次试试: 
describe('iTesting Demo', () => {  Cypress._.times(20, (k) => {    it(`欢迎关注iTesting ${k}`, () => {      cy.visit('/?delay=500')      cy.get('.loading').should('be.visible')      cy.get('.loading').should('not.be.visible')      cy.get('li.todo').should('have.length', 2)    })  })})

多次运行能够暴露出代码中的潜在问题,我建议所有要上CI运行的测试用例在提交到代码仓库时,都这样多次运行下!

这世界上啊,什么事都怕你有目的。果然目标一定,出现错误的次数就增加到过5次了。

那么我们确定,代码是有问题,再一眼一眼看吧。这个时候,有条件的你可能也要看下开发的代码如何写的。例如,visit的时候发生了什么, click的时候哪些事件被触发了? 通过了解开发逻辑可以帮助你快速定位问题。


经过一番调查啊,猜测出问题的代码在第4行和第5行。当元素(类名”.loading“)加载速度过快时候,就大概率会引发失败。


来初步验证下:
describe('iTesting Demo', () => {  it('欢迎关注iTesting', () => {    cy.visit('/?delay=500')    cy.get('.loading').should('be.visible')    cy.wait(1000)    cy.get('.loading').should('not.be.visible')    cy.get('li.todo').should('have.length', 2)  })})
哎,加了等待就不会出这个bug了。说明问题就在这里了:

也就是说,元素已经完成show的操作并且马上变成disappear了,但Cypress的Test Runner还没反应过来,还在检查元素show出来没。 


05

结论


然后就是各种查资料, 最后发现Cypress早有结论:

1. 如果一个元素出现和消失的间隔在21ms内,那么大概率TestRunner会“瞎”。

有的同学可能会想, Test Runner看不见,有没有其它办法能看见?比如Cypress不是提供视频可以录制运行中的所有情况么?我把运行过程录制下来慢慢查不就行了?

1. 不行!标准的视频,是每秒30帧, 每帧的标准间隔是33ms。


06

解决之道


既然找到了Root cause,解决起来就简单了,有如下解法:

  • 1. 加Sleep time

// 强烈不推荐, 用了我大Cypress,是不可能sleep的!cy.wait(1000) 
  • 2. 使用cy.intercept等待网络请求返回并加装完成后再执行

// 强烈推荐!cy.intercept('XXX你的代码').as('myRequest')cy.wait('@myRequest')xxxxx   //  你的后续代码
  • 3. 直接模拟服务器延迟返回

 //五星好评,强烈推荐!  cy.intercept('/todos', {    fixture: 'todos.json',    delayMs: 1000,  })


Cypress有很多奇淫巧技, 我已经总结超过百篇


别走开,下一篇更精彩!



往期回看:

                    你不知道的Cypress系列(1) --鸡肋的BDD

                    你不知道的Cypress系列(2) -- ”该死"的PO模型!

                    你不知道的Cypress系列(3) -- 是时候重构自己的思维了!

                    你不知道的Cypress系列(4) -- “PO”已死,App Action当立?


为了更好的支持我创作,麻烦同学们动动小手,点赞 + 在看 + 转发一键三联:)



技术讨论

公众号里直接回复 666, 带你入圈。


 -   -  时人莫小池中水, 浅处不妨有卧龙  -  -

作者:

Kevin Cai, 江湖人称蔡老师。

两性情感专家,非著名测试开发。

技术路线的坚定支持者,始终相信Nobody can be somebody。      


· 猜你喜欢的文章 ·

功能测试进阶系列直播(免费)

前端测试框架Cypress从入门到精通

自研测试框架ktest介绍(适用于UI和API)

测试开发入门与实战

浏览 18
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报