关于PO设计模式的介绍
POM概述
Page Object Model (POM) 是一种设计模式,通常用于自动化测试中,主要思想是通过分层的方式将对象、操作、业务分开处理以减少和业务逻辑或判断的耦合度,从而提高测试用例的可维护性
Martin Fowler 提出编写测试用例的POM的设计模式,后续在selenium等自动化测试框架中都得到很好的应用
为什么选择POM
如当你对web页面进行自动化测试时,你需要操作该web页面上的元素来点击链接或验证显示的内容。你可以在测试代码中直接操作html元素,进行一连串的操作后进结果进行断言验证。但当页面UI发生变化时,你的测试代码将变得极其脆弱。而且当测试用例多起来过后,这样的测试用例将变得不可维护。
这时候我们就需要采用POM,一个page对象(一个类对象)可以封装一个html页面或部分页面(这里的page不一定是一个完整的页面,也可以是该页面的一个特定模块,可以根据自己的业务需求来进行封装),在每个page中通过提供特定的API(特定的函数/方法)来操作页面元素(把元素信息和操作细节封装到page类中),而不需要在测试用例中来对html元素进行操作。
以后当html元素发生变化时,只需要修改page 类文件中的特定方法中的元素操作,而不需要修改所有的测试用例。这有助于使代码更具可读性、可维护性和可复用性。
POM的优点
- 可维护性
- 可复用性
- 可读性和可靠性
怎么实现POM
如以下测试用例:打开登录页面--> 输入用户名密码-->点击登录-->跳转主页-->验证主页面包含用户id
在这我们就可以封装两个page:LoginPage(登录页),HomePage(主页)
伪代码如下:
- LoginPage
username = By.name("uid");
password = By.name("password");
login = By.name("btnLogin");
setUserName(strUserName) {
driver.findElement(username).sendKeys(strUserName);
}
setPassword(strPassword) {
driver.findElement(password).sendKeys(strPassword);
}
clickLogin() {
driver.findElement(login).click();
}
login(strUserName, strPassword) {
setUserName(strUserName);
setPassword(strPasword);
clickLogin();
}
- HomePage
homePageUserName = By.xpath("//table//tr[@class='heading3']");
getHomePageUserName() {
return driver.findElement(homePageUserName).getText();
}
- testcase
setup();
test_Login {
LoginPage.login("monkeyjerry", "123!123");
Assert.assertTrue(HomePage.getHomePageUserName().toLowerCase().contains("manger id : monkey"));
}
POM编写的六大原则
- The public methods represent the services that the page offers
- Try not to expose the internals of the page
- Generally don't make assertions
- Methods return other PageObjects
- Need not represent an entire page
- Different results for the same action are modelled as different methods
翻译及理解:
- 公共方法代表页面提供的服务。比如点击页面中的元素跳到到新的页面,于是就可以为这个服务封装方法:“进入新页面”
- 不要暴露页面内部细节。只对外提供方法(接口)
- 不要在页面中使用断言。在页面中的操作中不要使用断言,断言放在测试用例中
- 方法可以return到新打开的页面。点击一个按钮跳转到新的页面,这个页面如登录成功页面,则可return到新的po如PersonalCenterPage
- 不要把页面整个内容放在page中。只为页面重要的元素进行po设计
- 相同的行为可产生不同的结果,可以封装成不同的方法。如登录操作,可以封装login_success(), login_error()两个方法
编写规则扩展
- 总体规则
所有模块设计均遵循 page object 结构
- 用例层:测试人员编写测试用例代码的地方,可以调用 page 层和封装层
- page 层:一个页面一个类,包含该页面的业务逻辑封装以及部分控件定义
- 封装层:根据业务需要,封装常用的业务逻辑 (相比于 page 层的业务逻辑封装,它的范围更广,有些时候是跨页面的业务逻辑。 属于模块级的业务封装)
- 页面设计规则
- 所有导航,页面辅助以及会跨越多个页面的逻辑均设计为接口,接口中定义默认实现
- 每个 page 类只负责自己页面的逻辑
- 页面类的类名以 Page 为结尾。 接口 (共用逻辑) 不得使用 Page 结尾
- 每个页面以封装业务逻辑为主,通过参数控制调用不同的业务逻辑。 无特殊情况下不要让外界知道控件的信息
- 所有页面逻辑皆返回特定页面对象,以保证测试用例使用 workflow 式 API
- 用例编写规则
- 每个 case 都必须使用 Features,Stroies, Title 标注来为 case 添加 report 信息 (我们使用的是 allure 这个 report 框架), 根据情况可以添加 Description 标注
- case 中涉及 UI 上创建的实体名称,比如项目,数据,模型,用户等都需要使用随机名称。 不能使用固定名称。 以防一个环境多次运行的时候因为名称冲突而失败
- case 中不准许出现页面元素信息,所有页面元素的封装和业务逻辑的封装要写在 page 层中