Cypress系列(62)- 改造 PageObject 模式
如果想从头学起Cypress,可以看下面的系列文章哦
https://www.cnblogs.com/poloyy/category/1768839.html
PO 模式
PageObject(页面对象)模式是自动化测试中的一个最佳实践,相信很多小伙伴都知道的
PO 模式特征
- 将每个页面(或者待测试对象)封装成一个(class),类里面包含了页面上所有元素及它们的操作方法(单步操作或功能集合)
- 测试代码和被测页面代码解耦,使用 PO 模式后,当页面发生改变,无须改变测试代码,仅改页面代码
接下来就讲解下 Cypress 下如何使用 PO 模式
前期准备
启动 Cypress 提供的演示项目
cmd 窗口进入下面的文件夹

执行下面的命令
npm start
PO 模式代码
简单的 PageObject 模型栗子
待测试页面代码
在 C:\Users\user\Desktop\py\cypress-example-recipes\examples\logging-in__html-web-forms\cypress 文件夹下新建 pages 文件夹,并创建一个 login.js 待测试页面文件,代码如下
// login.js
export default class LoginPage {
constructor() { this.userName = 'input[name=username]'
this.password = 'input[name=password]'
this.form = 'form'
this.url = 'http://localhost:7077/login'
} isTargetPage() {
cy.visit('/login')
cy.url().should('eq', this.url)
} login(username, pwd) {
cy.get(this.userName).type(username)
cy.get(this.password).type(pwd)
cy.get(this.form).submit()
} }
测试用例文件
在 C:\Users\user\Desktop\py\cypress-example-recipes\examples\logging-in__html-web-forms\cypress\integration 文件夹下,创建一个 testLogin.js 测试用例文件,代码如下
import LoginPage from "../pages/login"
context('登录测试,PO 模式', function () {
const username = 'jane.lane'
const pwd = 'password123'
it('登录成功', function () {
// 创建 po 实例
const loginInstance = new LoginPage()
loginInstance.isTargetPage()
loginInstance.login(username, pwd)
cy.url().should('include', '/dashboard')
});
})
测试结果

总结下
这样的 PageObject 模式代码只是把定位元素的元素定位表达式给剥离出来,并没有针对元素本身进行封装
针对元素本身进行封装的栗子
待测试页面代码
// login.js
export default class LoginPage {
constructor() {
this.userNameLocator = 'input[name=username]'
this.passwordLocator = 'input[name=password]'
this.formLocator = 'form'
this.url = 'http://localhost:7077/login'
}
get username() {
return cy.get(this.userNameLocator)
}
get password() {
return cy.get(this.passwordLocator)
}
get form() {
return cy.get(this.formLocator)
}
isTargetPage() {
cy.visit('/login')
cy.url().should('eq', this.url)
}
login(username, pwd) {
this.username.type(username)
this.password.type(pwd)
this.form.submit()
}
}
跳转页面代码
当登录成功后,页面将跳转至 mainPage 页面,上面只写了 login 页面,这里写下跳转后的页面
// login.js
export default class mainPage{
constructor() {
this.h1Locator = 'h1'
this.url = 'http://localhost:7077/dashboard'
}
get welComeText() {
return cy.get(this.h1Locator)
}
isTargetPage() {
cy.url().should('eq', this.url)
}
}
测试用例代码
测试用例代码和上面的栗子一样哦!不需要变!
测试结果

总结下
- login.js 和 mainPage.js 两个页面对象都有一个 isTargetPage() 函数来判断当前页面 URL 是否正确
- 那这里就将每个 page 都共用的部分再次剥离,放到一个新的 common page
- 然后每个 page 都继承自 common page(类似 selenium po 模式的 BasePage)
使用 common page 的栗子
commonPage.js 的代码
它也在 pages 文件夹下创建
export default class commanPage {
constructor() {
// 构造函数可以为空
// 如果不为空 应该是所有 page 都会用到的变量
}
isTargetPage() {
cy.url().should('eq', this.url1)
}
}
login.js 的代码
// login.js
import commanPage from "./commonPage"; // 继承 commonPage
export default class LoginPage extends commanPage{
constructor() {
// 调用父类的构造方法
super()
this.userNameLocator = 'input[name=username]'
this.passwordLocator = 'input[name=password]'
this.formLocator = 'form'
this.url = 'http://localhost:7077/login'
} get username() {
return cy.get(this.userNameLocator)
} get password() {
return cy.get(this.passwordLocator)
} get form() {
return cy.get(this.formLocator)
} visitPage(){
cy.visit('/login')
} login(username, pwd) {
this.username.type(username)
this.password.type(pwd)
this.form.submit()
} }
mainPage.js 的代码
// login.js
import commonPage from "./commonPage"; // 继承 commonPage
export default class mainPage extends commonPage {
constructor() {
super()
this.h1Locator = 'h1'
this.url = 'http://localhost:7077/dashboard'
} get welComeText() {
return cy.get(this.h1Locator)
}
}
测试结果
测试结果和上面的栗子一样
Cypress 使用 PO 模式的总结
- Cypress 完全支持 PageObject 模式
- 但存在一个问题,如果一个测试需要访问多个页面对象,就意味着测试中要初始化多个页面对象实例(new Page())
- 如果一个页面对象需要登录才能访问(大部分场景都是这样),则每次初始化都需要先登录再访问(只有登录后才能重用 cookie),这无形增加了测试运行的时间
- Cypress 不认为 PO 模式是一个好模式,它认为跨页面共享逻辑是一个反逻辑,因为 Cypress 的实现原理与其他工具完全不同
- 那 Cypress 用什么方式来替代 PO 模式呢?答案就是下一篇要讲到的 Custom Commands
Cypress系列(62)- 改造 PageObject 模式的更多相关文章
- Cypress系列(63)- 使用 Custom Commands
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html Custom Commands 自定义命 ...
- Cypress系列(1)- Window下安装 Cypress 并打开
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 系统要求 Cypress 是一个被安装在 ...
- Cypress系列(69)- route() 命令详解
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 作用 管理控制整个网络请求 重要注意事项 ...
- 浅谈pageobject模式
先来看两段代码 代码1: package com.zlshuo.selenium.nonaming.pageobject; /** * @author leshuo * @version 2014年5 ...
- CDC不同模式在ODI体现系列之二 异步模式
CDC不同模式在ODI体现系列之二 异步模式 2 异步模式需要在数据库中做一些准备工作: 改数据为归档并启用logminer: SQL> shutdown immediate 数据库已经关闭. ...
- 【转】Android总结篇系列:Activity启动模式(lauchMode)
[转]Android总结篇系列:Activity启动模式(lauchMode) 本来想针对Activity中的启动模式写篇文章的,后来网上发现有人已经总结的相当好了,在此直接引用过来,并加上自己的一些 ...
- PageObject模式的层次结构
做过UI自动化的都晓得,在做UI自动化时定位特别依赖页面,一旦页面发生变更就不得不跟着去修改页面定位. 在webdriver中,假设你想对一个元素定位操作,那么你可能会编写下面的代码: driver. ...
- Spartan6系列之芯片配置模式详解
1. 配置概述 Spartan6系列FPGA通过把应用程序数据导入芯片内部存储器完成芯片的配置.Spart-6 FPGA可以自己从外部非易失性存储器导入编程数据,或者通过外界的微处理器.DSP等对 ...
- Cypress系列(70)- server() 命令详解
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 作用 启动服务器以开始将响应路由到 cy ...
随机推荐
- HDU - 1005 -Number Sequence(矩阵快速幂系数变式)
A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) m ...
- 模拟CMOS集成电路 课后习题总结(2.1)
前几天开始自学拉扎维的模设教材,看之前浏览了EETOP论坛里面好多大神们对这本书的看法,当然也有人在抱怨,比如冒出“太科幻”.“一年才看完”之类恐怖的修饰语句,因此在开始看的时候就对此书充满了“敬畏” ...
- Java中构建长字符串的四种模式
回字有四种写法,构建字符串也有四种方式. 用+号最快,第二第三种可读性好,第四种是log4j自有的.下面请见代码: package logbackCfg; import java.text.Messa ...
- python之requests.session()使用
背景:使用requests.session会话对象先登录至豆瓣网,再进入“我的豆瓣”. 首先说一下,为什么要进行会话保持的操作? requests库的session会话对象可以跨请求保持某些参数. 说 ...
- linux下禁止root和匿名用户登录ftp
1.ftp通过root或其他用户进入可视化界面权限过大,容易导致系统文件误删 windows下输入ftp://IP去访问,不需要账号密码就可以访问到ftp文件夹 刚进去pub是空的,在linux上新增 ...
- Node.js 从零开发 web server博客项目[接口]
web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...
- PG-跨库操作-postgres_fdw
接上一篇<PG-跨库操作-dblink>:讲下postgres_fdw的使用:postgres_fdw工作原理详细介绍可以去看下<PostgreSQL指南>第4章: 对FDW特 ...
- 栈帧的内部结构--操作数栈(Opreand Stack)
每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...
- 面试题总结:可能是全网最好的MySQL重要知识点
标题有点标题党的意思,但希望你在看了文章之后不会有这个想法--这篇文章是作者对之前总结的 MySQL 知识点做了完善后的产物,可以用来回顾MySQL基础知识以及备战MySQL常见面试问题. 什么是My ...
- Shell学习(五)Shell输出命令
一.echo命令 #1.直接显示字符串 echo "It is a test" #输出:It is a test #2.显示转义字符 echo "\"It is ...