PO模式
PO是PageObject(页面对象)的缩写,PO模式是自动化测试项目开发中最常用的一种设计模式,PO模式的核心思想就是通过对页面元素的封装来减少代码的冗余性,提高代码的可维护性,假设后期维护中,若定位元素发生变化,需要调整页面元素封装的代码,从而提高测试用例的可维护性,以及代码的可读性。
PO模式可以把一个页面分成三层:对象库层。操作层、业务层
- 对象层:主要封装定位元素的方法
- 操作层:封装对元素的操作
- 业务层:将一个或者多个操作组合成一个业务功能,以登录功能为例:需要输入用户名、输入密码、点击登录按钮三个操作
不使用PO模式
假设我们要对一个登录页面做UI自动化测试,以某知名同性交友网站。假设需要测试多个登录成功、登录失败等多个场景,以下面这种写法就要写很多的冗余代码,而且并不好维护,假设前端将页面元素进行调整,我们需要修改脚本,就需要大量的重构,并且这样的写法可读性也不高。
Feature('demo');Scenario('loginOk', ({ I }) => {I.amOnPage('https://github.com/login');I.see('GitHub');I.fillField({xpath : "//input[@name='login']"},'test@qq.com');I.fillField({css : '#password'},'123456');I.click({xpath : "//input[@type='submit']"});I.see('Home');
});
Scenario('loginFail', ({ I }) => {I.amOnPage('https://github.com/login');I.see('GitHub');I.fillField({xpath : "//input[@name='login']"},'test@qq.com');I.fillField({css : '#password'},'666666');I.click({xpath : "//input[@type='submit']"});I.see('Home');
});
使用PO模式
同样是登录假设使用的PO模式,代码如下:
封装页面对象LoginPage和对应的操作方法
const { I } = inject();
module.exports = {// 定义页面元素选择器fields : {usernameInput : {xpath : "//input[@name='login']"},passwordInput : {css : "#password"},loginButton : {xpath : "//input[@type='submit']"}},// 定义页面元素操作方法enterUsername(username) {I.fillField(this.fields.usernameInput, username);},enterPassword(password) {I.fillField(this.fields.passwordInput, password);},clickLogin() {I.click(this.fields.loginButton);},login(username, password) {this.enterUsername(username);this.enterPassword(password);this.clickLogin();}
}
测试的业务逻辑
const loginPage = require('../pages/LoginPage')Feature('demo');Scenario('loginOk', ({ I }) => {I.amOnPage('https://github.com/login');I.see('GitHub');loginPage.login('test@qq.com','test');I.see('Home');
});
Scenario('loginFail', ({ I }) => {I.amOnPage('https://github.com/login');I.see('GitHub');loginPage.login('test@qq.com','666');I.see('Incorrect username or password.');
});
通过PO模式可以让测试脚本的可读性和可维护性更强,将页面对象和操作进行封装后可以被后续的多个测试场景复用,避免页面元素发生变化就大量修改代码。这种解耦合分离思想,在UI自动化测试中是十分推荐的,包括后续的错误日志记录,测试报告生成都可以分离到指定目录中,让整个脚本的结构清晰便于定位问题和维护。