将元素定位器剥离
首先在工程的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
///
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
///
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模式实现完毕
如果一个测试需要访问多个页面对象,这就意味着测试过程中需要初始化多个页面对象的实例,如果大多数页面对象需要 登陆才能访问,则每次初始化都需要先登录再访问,因为只有登陆后才能重用cookie,这无疑会增加测试执行的时间
因此在Cypress中并不认为PO是个很好的模式,Cypress认为跨页面共享逻辑是一个反模式(Anti-Pattern),在Cypress中,它提供了很多方式,允许用户通过更简单的方式直接设置被测应用程序达到的待测试状态,不需要再不同页面一遍又一遍的执行相通操作,这个更简单的方式就是***Custom Commands***