iTesting软件测试知识分享

你不知道的Cypress系列(11) -- 使用cy.session()加速鉴权

在Cypress中国群内、在公众号iTesting里,我每天都能看到大量关于Cypress的使用讨论和私下问询。这让我感到无比荣幸。[买了书的同学们,公众号回复你的微信,拉你到Cypress中国群]。

点击购买前端自动化测试框架 – Cypress从入门到精通

(一)鉴权的问题

鉴权(authentication)是指验证用户是否拥有访问系统的权利。在自动化测试中特制登录态的保持。 当前登录态的保持,存在如下痛点:

  1. 每次测试开始前必须重新登录。

  2. 在通过一个测试中,切换账户登录需要先登出。

针对第一个问题, 当前普遍的做法是将登录命令封装在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。

1
yarn upgrade cypress@8.2.0

其次,在项目根目录下的cypress.json文件里,添加如下设置。

1
"experimentalSessionSupport": true,

最后,更新登录的代码,使用cy.session。

1
2
3
4
5
6
7
8
9
10
// 关注公众号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
2
1. beforeEach()中写了cy.login(),多个测试用例中,只有第一次登录是真正的登录,剩余的cy.login()都是恢复缓存,不是真正的执行登录操作。节省了时间。
2. 当你在同个测试用例中切换账户,无需登出,直接登录即可。

下面列一个在同个测试用例中使用多个账户登录的场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 关注公众号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系列(1) –鸡肋的BDD

你不知道的Cypress系列(2) –该死的PO模型​

你不知道的Cypress系列(3) – 是时候重构你的思维了

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

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

你不知道的Cypress系列(6) – 多Tab的小秘密

你不知道的Cypress系列(7) – 当iFrame遇见弹出框

你不知道的Cypress系列(8) – “可视化”测试你知多少?

你不知道的Cypress系列(9) – 代码“自动生成”术。

你不知道的Cypress系列(10) – CypressHelper

你不知道的Cypress系列(11) – 使用cy.session()加速鉴权

🐶 您的支持将鼓励我继续创作 🐶
-------------评论, 吐槽, 学习交流,请关注微信公众号 iTesting-------------
请关注微信公众号 iTesting wechat
扫码关注,跟作者互动

本文标题:你不知道的Cypress系列(11) -- 使用cy.session()加速鉴权

文章作者:请关注微信公众号 iTesting

发布时间:2021年09月30日 - 23:09

最后更新:2021年12月10日 - 23:12

原始链接:http://www.helloqa.com/2021/09/30/你不知道的Cypress系列/你不知道的Cypress系列11使用cy.session加速鉴权/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。