前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你不知道的Cypress系列(2) -- ”该死"的PO模型​!

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

作者头像
iTesting
发布2021-01-04 14:24:18
2.3K1
发布2021-01-04 14:24:18
举报
文章被收录于专栏:iTesting

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

除了日常推荐大家通过阅读我的书来解决日常Cypress使用问题外,我也一直在更新着我这边的Cypress知识图谱, 不夸张的说,目前我总结和实践下来知识点多达200多篇。本着“雕琢自我,普惠他人”的原则,我决定在公众号iTesting上开设<你不知道的Cypress系列>专栏。此专栏目的是分享一些我自己趟过的坑,走过的弯路、以及在选型时抛弃了的实践。希望让大家在选用Cypress作为前端自动化测试框架方案时, 可以借鉴一下,避免再走我走过的弯路。

今天是<你不知道的Cypress系列>的第二篇 -- 绝知此事要躬行,别被Cypress官方忽悠瘸了!

为了让大家看到标题就知道我再说什么,我把标题更改为:

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

01

PO模型是什么

无论你基于何种自动化测试框架开发你的测试脚本,PO模型绝对是你绕不过的坎儿。

PO模型(Page Object Module)算得上自动化测试的最佳实践之一,其中心思想如下:

  • 把物理上的页面或者逻辑上的功能组合当成一个Page 类处理。
  • 针对每一个Page类,将此Page上所属的元素、此Page类上元素动作的组合分别封装成Object, 以及Class Methods。
  • 所有针对此页面的操作以Page 类的实例引用。

从代码实现上来看,元素、元素操作、 Page类、Page类对应的测试类就是PO。

实现PO模型后,测试用例的操作细节会被隐藏,转而以面向对象,或者说,以业务角度展示操作步骤,我们直接看一个PO封装后的测试用例:

代码语言:javascript
复制
import LoginPage from "../pages/login"
import mainPage from "../pages/main"


describe('PageObject模式之登录测试', function () {
// 关注公众号iTesting,玩转Cypress
const username = 'iTesting'
const password = 'password123'

    it('登录成功', function () {
const loginInstance = new LoginPage()
        loginInstance.visitPage()
          .isTargetPage()
          .login(username, password)

const mainInstance = new mainPage()
        mainInstance.isTargetPage()
          .welComeText.should('contain', 'iTesting')
    })
})

从业务角度看,PO模型非常直观:

代码语言:javascript
复制
初始化LoginPage实例
访问LoginPage
判断LoginPage可访问
登录

接着访问mainPage(登录后会跳转的页面)
判断mainPage可访问
在mainPage上断言

02

PO模型的好处

由上文可以看到, PO模型的目的,主要是为了重用元素,做到每个元素定位、每个元素、甚至每个类方法,在整个项目中,有且仅有一处定义,其它都是调用。通过这样的方式,PO模型做到了即使在复杂项目中,也不会增加维护成本。

除此之外,在当前微服务开发模式下,动辄十几个、几十个微服务会同步进行开发。那么,过去那种一个测试工程师搞定所有自动化测试的机会不再有了。当前大多数公司的实践是将测试框架收归专门团队负责,而将自动化脚本的编写下放到各微服务团队。对应的, 各个团队下的业务测试工程师要具体负责其微服务的自动化测试。

PO模型天然带来一个好处,即,Page类天然隔离了模块和团队。例如我是团队A的测试工程师,除去公用Page外,我只需要关注我这个微服务下的所有Page类及类方法即可。而不必关心其它团队所own的页面。

如果我对其它组的服务有依赖,这些通常会构建专门的函数并成为Common Page的一部分。

如果有新人进来,他的学习成本只是我们团队负责的页面 + 公用Page,相对来说比较友好。

03

Cypress怎么看PO模型

正如Cypress官方所宣扬的一样:

代码语言:javascript
复制
// The page object pattern isn’t actually anything “special”.

换句话说, Page Object只是方便重用而已,没什么大不了。

Cypress官方觉得Page Object模型里的大量Page类及其对应的测试类的使用,会加重调用链条,隐藏各个操作之间的动作细节,加重使用者的负担, 具体来说:

  1. 使用PO模型人为的在测试中引入了其他状态,这些状态是你(测试脚本创建者)自己定义的,而不是应用程序内部拥有的, 它增加了debug成本。
代码语言:javascript
复制
// 这个假设是成立的,因为程序内部并没有Page,更遑论Page里的方法。
// 那么当你运行失败时发现,Page.addWallet失败了,你无法直接知道哪里出错
// 你必须找到addWallet的定义,再去查看其实现,才能知道哪里错。

2. 使用PO模型使得测试速度变慢。

代码语言:javascript
复制
// 这也是事实。
// 毕竟你每次操作都要先initial Page实例,然后再寻找类方法,最后才是执行。

3. 使用PO模型使代码陷入“Conditional Testing”的怪圈。

代码语言:javascript
复制
// 比如你的方法里存在如下判断:
// 如果页面发生AAA, 你会进行BBB操作, 如果发生CCC,你会进行DDD操作。
// 这在Cypress看来是反模式。因为Cypress跟你的应用程序运行在同一个生命周期。
// Cypress可以捕获应用程序里发生的一切。
// 所以,你理应知道你的操作引发的结果到底是AAA还是CCC。

这3条, 条条剑指PO模型的七寸。

Cypress官方又说,好既然PO不好用, 而且它存在只是为了方便重用,那么我给你更好的办法:

于是Custom Commands出炉了。Custom Commands你可以看成是PO模型里的Common Page。所有在Custom Commands里定义的方法,天生可以被任何测试之间调用。相当于你生成了自己的全局命令。

来看一个Custom Commands的具体例子:

代码语言:javascript
复制
Cypress.Commands.add('login', (username, password) => {
    Cypress.log({
        name: 'login',
        message: `${username} | ${password}`,
    })
    // 关注公众号iTesting,精通Cypress使用
return cy.request({
        method: 'POST',
        url: '/login',
        form: true,
        body: {
            username,
            password,
        },
    })
})

这样,在使用上,你也不需要管什么Login Page类,Login测试类了。你在任何代码里直接写:

代码语言:javascript
复制
cy.login("关注iTesting,玩转Cypress")

它自然帮你登录成功, Page是什么?顿时不香了好吗!

Custom Commands的具体用法我的新书<前端自动化测试框架 -- Cypress从入门到精通>里讲的还算通透,这里就不多说。

另外,在JavaScript世界里, 很讲究一个链式调用(Chainable), Custom COmmands + 链式调用,Cypress认为它完全可以取代PO模型。

通过chainable把你的所有操作“可视化”。于是,一个Cypress推崇的测试用例就变成这样:

代码语言:javascript
复制
/// <reference types="cypress" />

describe('Custom Commands模式之登录测试', function () {
// 关注公众号iTesting,玩转Cypress

    it('登录成功', function () {
          cy.login(username, password)
            .verifyLoginSuccess()
            .verifyWelcomeTxt()
    })
})

从cypress角度,你看到的是login成功后直接去验证welcome的文本在不在。

这样感觉代码量是不是更少,代码更直观了?

03

我怎么看PO和Custom Commands

这里我也谈下我对PO和Custom Commands的看法。

首先要谨记:Cypress的出现是为Developer服务的,它对Developer的友好程度要高于Tester。

基于此,我们再来看登录成功这个用例, 你看到的是

代码语言:javascript
复制
cy.xxx()
   .yyy()
   .zzz()

这样的模式调用链清晰,从层次上来是,也比PO模型少了一层。出错后的调试,也更方便。

但是!

你的测试用例都是cy这样,cy那样,当然对于Cypress官方来说,很成功,Visibility非常高,简直是Cypress的活广告,美滋滋啊!

可是,你的“业务”呢?

不错!你的业务以及业务细节被隐藏了!

虽然从Cypress的Custom Commands方式让测试写起代码来更爽,但是别忘记,在国内,我们还存在大量的测试人员,测试开发水平不足!(此时应该有广告,我的拉勾专栏<测试开发入门与实战>开栏24小时内售卖超10000+, 破了测试专栏的记录,值得你去拉勾上搜一下 :))

而且,从习惯上来说,国内的同学们更习惯从业务角度去理解测试。并且Custom Commands把所有的公用功能都写在一个文件里,对测试人员来说不友好,当我的测试用例超过10000条时,Custom Commands里的公用方法,恐怕也有几百个了。总不能我来一个新人,让他花上几周时间去熟悉所有的方法吧!况且,都微服务了,他以后基本也只负责其中一些测试,那么我让他学那么多跟他没关系的方法干嘛呢?

虽然Custom Commands也可以做到按照微服务组织,然后在每个微服务Folder下实现一个Custom Commands的子域。但是,这样做,你使用时候由要跟PO模型一样先引入再使用, 那么它跟PO模型又有什么区别呢?!!

04

PO和Custom Commands我都要

纸上得来终觉浅!

纸上得来终觉浅!

纸上得来终觉浅!

不能迷信权威!我刚开始搭建公司的前端框架时, 我就完全按照Cypress官方建议做,结果,当我的测试用例到达几千条时,我傻了,Custom Commands里的方法几百个,即使是我自己写的,但我自己也闹不清楚哪个做哪个用处,因为没有了Page做参考,时间一长,我很难从函数命名上看出这个方法应该在那个页面下使用, 更别说对框架不熟悉的新人了。

结果没办法,我重新返工了一遍,把特别核心的公用功能放到Custom Commands里,把跟业务有关的,还是以Page Object方式组织。放到微服务下,放到Page下,这样, 再来新人,我告诉他,你只要看这个commands这个文件还有你的微服务folder就好了。

所以, PO + Custom Commands + chainable是我的最佳实践, 以后我的测试用例就变成这样了。

/// <reference types="cypress" />

代码语言:javascript
复制
import mainPage from "../pages/main"
describe('PageObject模式之登录测试', function () {
// 关注公众号iTesting,玩转Cypress
const username = 'iTesting'
const password = 'password123'

    it('登录成功', function () {
        cy.login(username, password)
const mainInstance = new mainPage()
        mainInstance.isTargetPage()
          .welComeText.should('contain', 'iTesting')
    })
})

这下终于清静了!是么?

Cypress又提出了一个模型,App Actions, 同学,你想去尝尝鲜吗?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iTesting 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 你不知道的Cypress系列(2) -- ”该死"的PO模型
相关产品与服务
灰盒安全测试
腾讯知识图谱(Tencent Knowledge Graph,TKG)是一个集成图数据库、图计算引擎和图可视化分析的一站式平台。支持抽取和融合异构数据,支持千亿级节点关系的存储和计算,支持规则匹配、机器学习、图嵌入等图数据挖掘算法,拥有丰富的图数据渲染和展现的可视化方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档