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 ...
随机推荐
- Building(单调栈+凸包)
Problem Description Once upon a time Matt went to a small town. The town was so small and narrow tha ...
- 小程序开发-媒体组件image
image 图片组件,支持 JPG.PNG.SVG.WEBP.GIF 等格式,2.3.0 起支持云文件ID. 所有属性如下: Tips image组件默认宽度320px.高度240px image组件 ...
- 用Python写一个向数据库填充数据的小工具
一. 背景 公司又要做一个新项目,是一个合作型项目,我们公司出web展示服务,合作伙伴线下提供展示数据. 而且本次项目是数据统计展示为主要功能,并没有研发对应的数据接入接口,所有展示数据源均来自数据库 ...
- java多版本管理
背景 java版本的升级也比较频繁, 每年一个版本或更多 虽然java环境变量的配置无技术性可言, 但对于频繁切换也是比较枯燥的 java版本管理工具 sdkman: https://sdkman.i ...
- TomcatAJP文件包含漏洞
漏洞概述 2020年2月20日,国家信息安全漏洞共享平台(CNVD)发布关于Apache Tomcat的安全公告,Apache Tomcat文件包含漏洞(CNVD-2020-10487,对应CVE-2 ...
- DoS拒绝服务-工具使用hping3、nping等(四)
Hping3几乎可以定制发送任何tcp/ip数据包,用于测试fw,端口扫描,性能测试 Syn Flood – hping3 -c 1000 -d 120 -S -w 64 -p 80 --flood ...
- JAVA知识点 I/O流框架简要笔记
I/O 框架 流的概念 内存与存储设备之间传输数据的通道 流的分类 按方向[重点] 输入流:将<存储设备>中的内容读到<内存>中 输出流:将<内存>中的内容写到&l ...
- 对比 Redis 中 RDB 和 AOF 持久化
概念 Redis 是内存数据库,数据存储在内存中,一旦服务器进程退出,数据就丢失了,所以 Redis 需要想办法将存储在内存中的数据持久化到磁盘. Redis 提供了两种持久化功能: RDB (Red ...
- python文件的相关操作
python 目录 python 1.python文件的介绍 使用文件的目的 Python文件的类型主要有两种:文本文件和二进制文件. 操作文件的流程主要有三步:打开-操作-关闭操作. 2.文件的打开 ...
- Vue Render自定义tabled单元格内容
解决问题 只举一个例子(我正好需要用到的) 在写中后台时, 如果对 表格组件 再度封装了, 比如这样的 以element-ui 为例: <template> <el-table :d ...