iTesting,爱测试,爱分享
转眼之间,你不知道的Cypress系列已经到第11篇了。在Cypress中国群内、在公众号iTesting里,我每天都能看到大量关于Cypress的使用讨论和私下问询。这让我感到无比荣幸(买了书的同学们,公众号回复你的微信号,拉你到Cypress中国群)。
今天是你不知道的Cypress系列(11) -- 使用cy.session()加速鉴权。
鉴权(authentication)是指验证用户是否拥有访问系统的权利。在自动化测试中特制登录态的保持。 当前登录态的保持,存在如下痛点:
针对第一个问题, 当前普遍的做法是将登录命令封装在Custom Commands中(比如封装成cy.login()),然后在每个测试用例运行时,即beforeEach()中调用cy.login()。为了减少登录的次数,有些同学会使用before()这个前置操作,即在JS文件的一次执行中,无论有多少个测试用例,仅登录一次,登录后使用Preserve Cookies来保持登录态。Preserve Cookies相关代码一般写在index.js中,用于在获取登录态后保持它不被清除(这个方法你需要明确知道要保留那些Cookie)。但这个方法违背了每个测试用例应该是独立的、原子的这个特性。
针对第二个问题,,在同一个测试用例中使用不同账户登录,只能先登出第一个,然后再登录第二个。这无形中增加了整个测试用例的执行时间。
这两个问题的存在影响了测试效率,直到8.2.0发布,Cypress有了更好的解决办法。
我在书中以及无数次公开课中都提到过,鉴权最关键的就是登录态,而登录态,最关键的还是Session和Cookie。(Cookie和Session的知识参见我是如何面试的 -- 从一道面试题说开去)。而Cypress解决鉴权问题的思维很简单:
1. Cypress使用cy.session()命令在登录成功后,将cookies、localStorage和sessionStorage缓存起来。2. 当你下次再使用cy.login()登录时,将不再登录,而是将缓存的cookies、localStorage和sessionStorage恢复从而达到获取登录态的目的。
那么,如何使用cy.session()呢?
首先,你需要升级Cypress至8.2.0。
yarn upgrade cypress@8.2.0
其次,在项目根目录下的cypress.json文件里,添加如下设置。
"experimentalSessionSupport": true,
最后,更新登录的代码,使用cy.session。
// 关注公众号iTesting,跟万人测试团一起成长
Cypress.Commands.add('login', (username, password) => {
cy.session([username, password], () => {
cy.visit('/login')
cy.get('[data-test=username]').type(username)
cy.get('[data-test=password]').type(password)
cy.get('#login').click()
cy.url().should('contain', '/login-successful')
})
})```
最后,你就可以无感使用啦, 使用场景如下:
1. beforeEach()中写了cy.login(),多个测试用例中,只有第一次登录是真正的登录,剩余的cy.login()都是恢复缓存,不是真正的执行登录操作。节省了时间。2. 当你在同个测试用例中切换账户,无需登出,直接登录即可。
下面列一个在同个测试用例中使用多个账户登录的场景。
// 关注公众号iTesting,跟万人测试团一起成长
it('多账户在同一个测试用例中登录', () => {
// 第一个账户登录
cy.login('iTesting', 'isGood')
// 注意,使用cy.session()后,cy.visit()不能省略,必须显式调用
// 原因看下面解释
cy.visit('/account')
cy.get('#amount').type('100.00')
cy.get('#send-money').click()
// 一般情况下,此时应调用cy.logout()函数
// 使用cy.session()后,无需调用cy.logout()函数
// 直接登录下一个账户
cy.login('另外账户', '另外账户密码')
cy.visit('/account')
cy.get('#balance').should('eq', '100.00')
})
需要注意的是:
1. 这个功能是试验性质的,还不属于正式功能。2. 在启用experimentalSessionSupport这个选项后,Cypress做了如下几件事: 1)只有这个选项enable后,cy.session()才能在测试用例中在使用。 2)Cypress.session API被添加了进来。Cypress.session 是一组与会话相关的辅 助方法,旨在与cy.session() 命令一起使用。 3)在每个测试用例开始之前: (1)被访问的页面被Cypress重设成about:blank (2)所有活动的Session数据被清除 (3)以下两个方法被重写:Cypress.Cookies.preserveOnce() Cypress.Cookies.defaults()
由于页面在每个测试用例执行前被清除,因此必须在每个测试用例中显式调用 cy.visit() 以访问应用程序中的页面。
使用cy.session(),Cypress仅会在第一次登录时候执行真正的登录操作,在同一个JS文件中的后续任何同个账户的登录操作,都将通过恢复Session的方式来进行。这种行为缩短了测试的时间。
Cypress有很多奇淫巧技, 我已经总结超过百篇
别走开,下一篇更精彩!
往期回看:
你不知道的Cypress系列(7) -- 当iFrame遇见弹出框
为了更好的支持我创作,麻烦同学们动动小手,点赞 + 在看 + 转发一键三联:)
技术讨论
公众号里直接回复 666, 带你入圈
- - 时人莫小池中水, 浅处不妨有卧龙 - -
作者: Kevin Cai, 江湖人称蔡老师。 两性情感专家,非著名测试开发。 技术路线的坚定支持者,始终相信Nobody can be somebody。