自动化测试框架[Cypress PO模式]

自动化测试框架[Cypress PO模式]【附源码】在Cypress中并不认为PO是个很好的模式,Cypress认为跨页面共享逻辑是一个反模式(Anti-Pattern),在Cypress中,它提供了很多方式,允许用户通过更简单的方式直接设置被测应用程序达到的待测试状态,不需要再不同页面一遍又一遍的执行相通操作

大家好,又见面了,我是你们的朋友全栈君。

Cypress的PO模型

将元素定位器剥离

首先在工程的Cypress路径下新建一个pages目录,然后在该目录下新建一个JS文件,并命名为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, password){ 
   
		cy.get(this.userName).type(username)
		cy.get(this.password).type(password)
		cy.get(this.form).submit()
	}
}

然后在Cypress路径下的integration路径下新建一个JS文件,并命名为testLogin.js

//testLogin.js
/// <reference types="cypress" />
import LoginPage from "../pages/login"
describe('登录测试,PageObject模式', function () { 
   
    const username = 'davie.yang'
    const password = 'yangdawei'
    it('登录成功', function () { 
   
    	// 创建pageobject实例
        const loginInstance = new LoginPage()
        loginInstance.isTargetPage()
        loginInstance.login(username, password)
        cy.url().should('include', '/dashboard')
    })
})

改造login.js

//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, passWord){ 
   
		this.username.type(userName)
		this.password.type(passWord)
		this.form.submit()
	}
}

在pages路径下新建JS文件,并命名为mainPage.js

//mainPage.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)
	}
}

更新testLogin.js文件,验证登陆成功后跳转到mainPage页面

//testLogin.js
/// <reference types="cypress" />
import LoginPage from "../pages/login"
import mainPage from "../pages/mainPage"
describe('登录测试,PageObject模式', function () { 
   
    const username = 'davie.yang'
    const password = 'yangdawei'
    it('登录成功', function () { 
   
        const loginInstance = new LoginPage()
        loginInstance.isTargetPage()
        loginInstance.login(username, password)
        cy.url().should('include', '/dashboard')
        const mainInstance = new mainPage()
        mainInstance.isTargetPage()
        mainInstance.welComeText.should('contain', 'davie.yang')
    })
})

进一步更新,将每个页面都公用的部分再次剥离,在pages路径下新建一个JS文件,并命名为commonPage.js

//commonPage.js
export default class CommonPage { 
   
    constructor() { 
   
        //构造函数,可以为空。
        //如果不为空,应该是所有 page 都会用到的变量。
    }
    isTargetPage() { 
   
        cy.url().should('eq', this.url)
    }

}

然后更新login.js文件

//login.js
import CommonPage from './commonPage'
export default class LoginPage extends CommonPage { 
   
    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, passWord) { 
   
        this.username.type(userName)
        this.password.type(passWord)
        this.form.submit()
    }
}

更新pages文件夹下的mainPage.js文件

import CommonPage from './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)
    }
}

到此一个PO模式实现完毕

Cypress的PO模式弊端

如果一个测试需要访问多个页面对象,这就意味着测试过程中需要初始化多个页面对象的实例,如果大多数页面对象需要 登陆才能访问,则每次初始化都需要先登录再访问,因为只有登陆后才能重用cookie,这无疑会增加测试执行的时间

因此在Cypress中并不认为PO是个很好的模式,Cypress认为跨页面共享逻辑是一个反模式(Anti-Pattern),在Cypress中,它提供了很多方式,允许用户通过更简单的方式直接设置被测应用程序达到的待测试状态,不需要再不同页面一遍又一遍的执行相通操作,这个更简单的方式就是***Custom Commands***

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137793.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • PropertyDescriptor属性描述类学习

    PropertyDescriptor属性描述类学习1构造方法通过调用getFoo和setFoo存取方法,为符合标准Java约定的属性构造一个PropertyDescriptor publicPropertyDescriptor(StringpropertyName, Class&lt;?&gt;beanClass) 该构造函数使用简单属性的名称,以及读取和写入属性的方法名称publicPropertyDes…

    2022年9月28日
    3
  • 开源 微商分销系统 php,[PHP程序] 微商新零售分销平台源码Thinkphp内核 产品营销推广神器…

    开源 微商分销系统 php,[PHP程序] 微商新零售分销平台源码Thinkphp内核 产品营销推广神器…源码介绍一个新零售的派单工具,有了平台,会让客户主动加你买货,100%成交,还会积极帮你转介绍,让你不仅仅获得派单,还能建立自己的商友圈,积累强大的人脉。平台的机制中一共分为13个商友星级,从一星到十三星,每升一星就会获得大量的平台派单,升到13星一共可获得百万笔零售订单。平台没有行业限制,无论你是微商,电商还是实体,无论你是卖衣服、化妆品还是食品,都可以使用平台。同行可以合作,异业可以联盟,不用…

    2022年5月17日
    37
  • MySQL索引的优缺点

    MySQL索引的优缺点一、什么是索引索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越高。如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。例如有三张表分别是t1、t2、t3,每个表都有字段a1、a2、…

    2022年5月26日
    33
  • Ubuntu安装gcc失败的那些事儿「建议收藏」

    Ubuntu安装gcc失败的那些事儿「建议收藏」想在虚拟机上运行一个C程序输入gcc-ohellohello.c编译C语言文件嗯?找不到gcc。。。那就下载gcc输入gcc安装命令sudoaptinstallgcc安装包即将下完的时候提示下载错误,(我滴天,什么人间疾苦!!!)有几个软件包下载不了,还建议我使用sudoapt-getupdate或者加上–fix-missing那就屈尊采纳一下它的建议使用sudoapt-getupdate更新了一下软件资源(然并卵。。。)再试一下sudoaptinstallgc

    2022年7月24日
    44
  • android 载入svg动画,Android 加载SVG动画[通俗易懂]

    android 载入svg动画,Android 加载SVG动画[通俗易懂]Android加载SVG动画SVG可以说是目前比较流行的图片格式,使用领域也十分广泛,例如:web前端页面,Androidios等移动应用。都可以使用SVG的图片格式。今天就要和大家谈一谈SVG在Android中的应用,SVG的引入其实在我之前的文章里已经有谈到。其实这个文章就是Android加载SVG的原理。文章地址点击进入(Path的高级用法)。还有一篇是谈到…

    2025年7月31日
    2
  • ElasticSearch join连接查询「建议收藏」

    ElasticSearch join连接查询「建议收藏」ElasticSearchjoin连接查询特别说明:文章所有内容基于ElasticSerch5.5.3版本ElasticSerch的连接查询有两种方式实现nestedparent和child关联查询nested存储结构nested的方式和其他字段一样,在同一个type里面存储,以数组的方式存储在type里,格式如下:PUTindex…

    2022年6月16日
    78

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号