代码改变世界

Selenium的PageFactory & PageObject 在大型项目中的应用

2017-07-16 00:45  清风软件测试开发  阅读(577)  评论(0编辑  收藏  举报

因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手动的操作步骤去转换,近日看到一个文章,又去wiki上查了查,觉得写的不错就记录下来了。

    在使用selenium做UI测试的时候,往往并不是页面的每个功能我们都要测试,总有一些经常要进行回归的功能,再细致一点的说,有一些节点是我们经常操作的,那么我从项目初期开始就进行自动化测试代码编写的话,我们可以设计适应项目的一套自动化测试代码结构,基本的思路就是对每一个页面都创建一个相应的PageObject类,如果是公共的模板页面当然只建立一个就可以了。这样下来就相当于建立了很多基础页面一样,如果项目开发的过程中还有完整的文档或者足够详细的用户故事,那么就简直太完美了~~因为这样你可以减少很多次的IDE----Browser之间的切换、查找、测试工作,真的方便很多。但是这个看项目而定吧,这种细致入微的文档很多团队似乎都没能做到。但是笔者还是真的希望在产品初期或项目开始的时候有完整的文档给我们这些自动化测试的人员手中,这样可以大大加快我们自动化测试代码的编写。绕的有点远了。。。回归正题,如何做这种一个页面一个基础类的实现呢?最实际的,看代码:

 

[java] view plain copy
 
  1. public class PageObject {  
  2.   
  3.     private WebElement searchTypeSng;  
  4.     private WebElement fromCity;  
  5.     private WebElement toCity;  
  6.     private WebElement fromDate;  
  7.   
  8.     public String calDate(int nextDays) {  
  9.         // 当前日期加 n 天之后   
  10.         Date date = DateUtils.addDays(new Date(), nextDays);  
  11.         // 格式化时间格式  
  12.         return DateFormatUtils.ISO_DATE_FORMAT.format(date);  
  13.     }  
  14.   
  15.     public void searchTrip(WebDriver driver,String from, String to ,String date) {  
  16.         BaseUtils.clearAndTypeString(driver,fromCity, from);  
  17.         BaseUtils.clearAndTypeString(driver,toCity, to);  
  18.         BaseUtils.clearAndTypeString(driver,fromDate, date);  
  19.         searchTypeSng.submit();  
  20.     }  
  21.   
  22. }  


测试执行:

 

 

[java] view plain copy
 
  1. public class UsingPageObject {  
  2.   
  3.     public static void main(String[] args) {  
  4.   
  5.         WebDriver driver = new FirefoxDriver();  
  6.   
  7.         EventFiringWebDriver eventDriver new EventFiringWebDriver(driver);  --------------加入监听
  8.           
  9.         eventDriver.register(new MyWebDriverListener());  -----------------------------注册自己写的监听器
  10.           
  11.         eventDriver.get("http://flight.qunar.com/");  
  12.           
  13.         PageObject object = PageFactory.initElements(driver, PageObject.class);  
  14.           
  15.         String date = object.calDate(30);  
  16.           
  17.         object.searchTrip(driver,"北京", "厦门", date);  
  18.           
  19.   
  20.     }  
  21. }  

这个时候就完成对搜索这一功能的冒烟测试,测试执行代码没有使用TestNG,只是直接用了一个main函数。为了写博客简单方便,不推荐大家效仿。

 

如果还需要测试其它功能和使用其它节点,直接在PageObject类中加入相应的Field即可。

分割线-------------------------------------------------------------------------------------------------分割线

写到这里,如果没用过这个方法的人会越看越晕,现在简单的讲解一下它执行的原理:

在PageObject类中我们创建的Field的名称是和页面有一定的对应关系的,不是随意取的,如果像上面代码这么写,默认的selenium会根据Id最先进行元素查找,如果没有查找到再通过name进行查找,下面的我就不说了,因为你已经想到了。。。如果你担心页面的不规范或者复杂度比较高,容易产生ID,name,Css等的冲突,selenium不能准确的识别元素, 那么请往下看:

selenium还提供了一种注解的方式,还是直接上代码:

 

[java] view plain copy
 
  1. public class PageObject {  
  2.     private WebElement searchTypeSng;  
  3.     @FindBy(name="fromCity")  
  4.     private WebElement fromCity;  
  5.     @FindBy(name="toCity")  
  6.     private WebElement toWhere;  
  7.     private WebElement fromDate;  
  8.   
  9.     public String calDate(int nextDays) {  
  10.         // 当前日期加 n 天之后 n=30  
  11.         Date date = DateUtils.addDays(new Date(), nextDays);  
  12.         // 格式化时间格式  
  13.         return DateFormatUtils.ISO_DATE_FORMAT.format(date);  
  14.     }  
  15.   
  16.     public void searchTrip(WebDriver driver,String from, String to ,String date) {  
  17.         BaseUtils.clearAndTypeString(driver,fromCity, from);  
  18.         BaseUtils.clearAndTypeString(driver,toWhere, to);  
  19.         BaseUtils.clearAndTypeString(driver,fromDate, date);  
  20.         searchTypeSng.submit();  
  21.     }  
  22.   
  23. }  


当你看到这两个annotations的时候,你已经明白了,是的,selenium提供注解的方式对页面的元素进行准确的定位,可以参考的关键字有:className、css、id、linkText、name、partialLinkText、tagName、xpath.

 

另外selenium还提供了2个关键字,一个是how,另一个是using,如何使用它们就不在这里写了,因为笔者觉得,用这两个关键字更麻烦,理解起来也麻烦。

关于PageObject & PageFactory的使用,就简单的写了这么多,关于PageFactory还有很多知识,我会抽出时间写在下篇文章里,如果有正在使用这种模式的朋友,请多多批评和指点,相互讨论学习。