设计模式
在了解PO模式之前,我们先了解下什么是设计模式。下面这段话摘录其他文章:
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
可以看出几个关键字: 解决方案、重用代码、让代码更容易,也就说设计模式的诞生是为了让项目开发迭代更快。
我第一次知道设计模式是在java语言中,大概常用的设计模式有23种之多
- 创建型模式(5种):工厂方法模式、抽象工厂模式、单列模式、建造者模式、原型模式。
- 结构型模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、访问者模式、中介者模式、解释器模式。
这些设计模式广泛应用现在的程序开发中,提高程序的复用性、降低代码的耦合性。
什么是PO?
刚了解自动化的时候,经常写一个java或者py文件脚本,在文件中写上百行代码。但是随着测试用例不断增加多,单独的脚本文件开始难以支撑自动化正常运行了,经常会出现执行某一个Case失败导致所有用例失败,修改某个用例导致脚本不能正常运行了等问题。
基于上面的问题,我开始思考如何能让脚本运行的更加稳定性、易用性呢? 第一步就是需要从框架的开发模式来着手,之前的单脚本模式类似面向过程编程,将问题分解成一个一个详细的步骤,然后通过函数实现每一个步骤,并依次调用。因此需要引入面向对象编程模式来解决问题,面向对象则是一种以对象为中心的编程思想,通过分析问题,分解出一个一个的对象,然后通过不同对象之间的调用来组合解决问题。
面向对象编程只是一种编程概念,通过在网络上调研了解,PO模式广泛运用在测试自动化领域。PO模式是page object model的缩写,是一种设计模式,实现脚本的page和项目构成映射起来,这样能测试框架更容易维护。
特点:
1、页面对象模型(PO)是一种设计模式,用来管理维护一组页面元素的对象库。
2、在PO下,应用程序的每一个页面都有一个对应的Page类。
3、每一个Page类维护着该页面的元素集和操作这些元素的方法。
优点:
1、代码可读性强: 有层次的设计感,让协同开发脚本的同学也能快速读懂代码。
2、可维护性高: 脚本执行的失败的地方,只需要改动某一层代码即可。
3、复用性高: 写其他测试用例,可以复用基础方法。
怎么设计PO?
设计的原则
1、抽象每一个页面
2、页面中元素不暴露,仅报错操作元素的方法
3、页面不应该有繁琐的继承关系
4、页面中不是所有元素都需要涉及到,核心业务元素做建模使用
5、把页面划分功能模块,在Page中实现这些功能方法
Appium的PageFactory模式
代码语言:javascript复制我用的是java写的脚本,使用appium java-client 6.1.0
java版的appium自带了PO工厂模式
//首先导入pagefactory.AppiumFieldDecorator类
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.openqa.selenium.support.PageFactory;
//构造方法中传入driver参数
public FunctionPage(AppiumDriver<?> driver) {
this.driver = driver;
//使用initElements方法构造,第一个参数new AppiumFieldDecorator,第二个参数是当前类
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
}
继承FunctionPage类
当然每个Page都可以构造AppiumFieldDecorator,但是这样显示是很麻烦。
需要建立通用的一个FunctionPage类
1、负责构造AppiumFieldDecorator,子类继承即可。
2、可以封装常用操作,子类调用即可。
代码语言:javascript复制
public class BuyPage extends FunctionPage{
public AudioPage audioPage;
private static final int Timeout = 5;
private static final String play = "播放";
@iOSFindBy( accessibility = "已购区")
@WithTimeout(time = Timeout,chronoUnit = ChronoUnit.SECONDS)
public IOSElement BuyArea;
/**
* 初始化页面
*/
public BuyPage(IOSDriver iosDriver) {
super(iosDriver);
//在子类构造的时候,调用FunctionPage
audioPage = new AudioPage(iosDriver);
}
}
**
* 听书借阅区
*/
public void borrowArea() throws InterruptedException {
BorrowArea.click();
log_info("听书借阅区");
BorrowList.click();
log_info("听书借阅区列表");
//调用FunctionPage中封装的断言方法
assertContain(play);
audioPage.Audioplay();
}
测试类使用PO
1、对于测试类,不应该有直接操作元素的方法。 测试步骤是使用每个Page中方法来完成一条测试用例。
2、page页面提供对外的方法,测试用例调用.让测试类更简洁、维护成本相对较少。
代码语言:javascript复制
/**
* 测试点:首页-电子书列表-新书上架
*/
@Test
public void test_newBookList() throws InterruptedException {
homePage.homeeBook();
eBookPage.newBookList();
}
结语
小结PO模型:
- PO建模交给父类,子类Page继承调用即可
- 父类负责封装常用方法,子类Page继承调用即可
- 让Page页面更简洁,公共部分的方法使用更高效
最后,PO模式也不是万能的,如果测试用例在百十条之内用PO模式是没什么问题的,如果测试用例上千以后的维护负责成本就会加剧了,到时候可能需要设计其他设计模式,如果你有什么更好的自动化框架设计模式,欢迎交流~。