浅谈pageobject模式
先来看两段代码
代码1:
package com.zlshuo.selenium.nonaming.pageobject; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AT { public static void main(String[] args){ //获取二手房经纪人电话
String telephoneNum=BasePage.get("http://shanghai.anjuke.com").
serachKeyWords("上海别墅").clickPorpByindex(1).getTelephoneNum(); System.out.println(telephoneNum); //退出driver
BasePage.quit(); }
}
代码2:
package com.zlshuo.selenium.nonaming.pageobject; import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AT1 { private static WebDriver driver;
public static void main(String[] args){ System.setProperty ( "webdriver.chrome.driver" ,
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe" );
WebDriver driver = new ChromeDriver();
driver.get("http://shanghai.anjuke.com");
driver.findElement(By.xpath("//input[@id='glb_search0']")).sendKeys("上海别墅");
driver.findElement(By.xpath("//input[@id='glb_search0']")).submit();
driver.findElement(By.xpath("//a[@id='prop_name_qt_prop_1']")).click();
driver=switchToWindow(2);
String telephoneNum=driver.
findElement(By.xpath("//div[@class='A-fangyuan-call']/p[@class='number']")).
getText();
System.out.println(telephoneNum);
driver.quit(); } public static List<String> getWindowHandlesList() {
Set<String> handles = driver.getWindowHandles();
List<String> list=new ArrayList<String>();
for (String s : handles){
list.add(s);
}
return list;
} public static WebDriver switchToWindow(int index) {
try {
int windowNumber=getWindowHandlesList().size();
if(windowNumber<=0){
Assert.fail("窗口数为0");
}else if(windowNumber==1)
;
else{
return driver.switchTo().window(getWindowHandlesList().get(index-1));
} } catch (NoSuchWindowException e) {
e.printStackTrace();
}
return driver; }
}
这两段代码完成的功能都是一样的:访问安居客搜索"上海别墅",点击搜索结果的第一套房源,获取经纪人的手机号码。
代码1看上去要简洁很多,采用pageobject模式,便于单个用例脚本的编写展示,代码2是用原生的selenium书写,高下立判。代码1用下面这个版本会更加容易理解一点
package com.zlshuo.selenium.nonaming.pageobject; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AT { public static void main(String[] args){ //访问安居客首页
AnjukeHomePage homePage=BasePage.get("http://shanghai.anjuke.com");
//搜索上海别墅二手房
AnjukeSaleListPage listPage=homePage.serachKeyWords("上海别墅");
//点击第一套房源
AnjukeSalePropPage propPage=listPage.clickPorpByindex(1);
//获取房源单页经纪人电话
String telephoneNum=propPage.getTelephoneNum(); System.out.println(telephoneNum); //退出driver
BasePage.quit(); }
}
先来看看BasePage,BasePage是所有页面的父类,其他页面需要继承之,他有两个方法get和quit.get用来初始化driver并访问url,quit用来退出driver,kill浏览器进程
package com.zlshuo.selenium.nonaming.pageobject; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver; /**
* @author leshuo
* @version 2014年5月14日
*/
public class BasePage { private static WebDriver driver; public static AnjukeHomePage get(String url){
System.setProperty ( "webdriver.chrome.driver" ,
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe" );
driver = new ChromeDriver();
driver.get(url);
return new AnjukeHomePage(driver);
} public static void quit(){
driver.quit();
} }
AnjukeHomePage是BasePage.get()返回的页面对象,这里定义为安居客首页,他有一个serachKeyWords方法,用于搜索关键词并返回列表页面
package com.zlshuo.selenium.nonaming.pageobject; import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AnjukeHomePage extends BasePage{ private WebDriver driver; AnjukeHomePage(WebDriver driver){
this.driver=driver;
} public AnjukeSaleListPage serachKeyWords(String words){
driver.findElement(By.xpath("//input[@id='glb_search0']")).sendKeys(words);
driver.findElement(By.xpath("//input[@id='glb_search0']")).submit();
return new AnjukeSaleListPage(driver);
} }
AnjukeSaleListPage是搜索列表页,此页面展示了搜索出的相关房源信息,我只写了一个选择房源的方法作为例子,点击房源后就进入了房源显示的页面了,所以clickPorpByindex返回的是房源单页对象AnjukeSalePropPage
package com.zlshuo.selenium.nonaming.pageobject; import java.util.ArrayList;
import java.util.List;
import java.util.Set; import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.testng.Assert; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AnjukeSaleListPage extends BasePage{ private WebDriver driver; public AnjukeSaleListPage(WebDriver driver){
this.driver=driver;
} public AnjukeSalePropPage clickPorpByindex(int index){
driver.findElement(By.xpath("//a[@id='prop_name_qt_prop_"+index+"']")).click();
//切换到新开的窗口
driver=switchToWindow(2);
return new AnjukeSalePropPage(driver);
} private List<String> getWindowHandlesList() {
Set<String> handles = driver.getWindowHandles();
List<String> list=new ArrayList<String>();
for (String s : handles){
list.add(s);
}
return list;
} private WebDriver switchToWindow(int index) {
try {
int windowNumber=getWindowHandlesList().size();
if(windowNumber<=0){
Assert.fail("窗口数为0");
}else if(windowNumber==1)
;
else{
return driver.switchTo().window(getWindowHandlesList().get(index-1));
} } catch (NoSuchWindowException e) {
e.printStackTrace();
}
return driver; }
}
AnjukeSalePropPage只有一个方法即获取经纪人电话
package com.zlshuo.selenium.nonaming.pageobject; import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver; /**
* @author leshuo
* @version 2014年5月14日
*/
public class AnjukeSalePropPage extends BasePage{ private WebDriver driver; public AnjukeSalePropPage(WebDriver driver){
this.driver=driver;
} public String getTelephoneNum(){
return driver.findElement(By.xpath("//div[@class='A-fangyuan-call']/p[@class='number']")).
getText();
}
}
不难看出,pageobject模式以业务逻辑上的每一步操作作为区分点,页面方法代表了此页面的一个业务操作并严格控制此操作的后续流程,这样做的好处有以下几点:
1.以页面为单位,重复的操作封装在一个方法中,当页面元素或流程变动时只需修改相关页面方法即可,不需要修改相应的脚本
2.测试脚本编写简单,顺着业务逻辑写脚本和手工测试一样的感觉。例如,访问安居客首页->搜索上海别墅->点击搜索结果的第一套房源进入房源单页->获取经纪人手机号码,写成脚本就是BasePage.get("http://shanghai.anjuke.com").serachKeyWords("上海别墅").clickPorpByindex(1).getTelephoneNum(),一气呵成。
3.可以和PageFactory模式一起使用,节约前期开发成本
当然,这些奇淫巧计都是锦上添花之物,真正的着落之处应该在规范流程及提高开发者个人水平这一方面。
先污染后治理的理念是要摒弃的。
浅谈pageobject模式的更多相关文章
- 浅谈MVVM模式和MVP模式——Vue.js向
浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...
- iOS:个人浅谈工厂模式
一.什么是工厂方法? 正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟到子类中进行.工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好 ...
- 浅谈MVC模式
MVC模式(三层架构模式) (Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...
- 设计模式浅谈----策略模式(c#及java实现)
一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...
- 浅谈MVC模式与MVVM模式的区别
MVC模式: M:Model(数据模型),用于存放数据 V:View(视图),也就是用户界面 C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给V ...
- Swift语言精要 - 浅谈代理模式(Delegate)
在iOS编程中,我们经常谈到代理代理,也就是delegate,那么什么是代理呢? 我们来看一下cocoa对它的描述: Delegation is Cocoa’s term for passing of ...
- 设计模式之——浅谈strategy模式(策略模式)
strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...
- 浅谈ThreadLocal模式
一.前言: ThreadLocal模式,严格意义上不是一种设计模式,而是java中解决多线程数据共享问题的一个方案.ThreadLocal类是java JDK中提供的一个类,用来解决线程安全问题,并不 ...
- 浅谈单利模式及其应用场景(Python)
python 中的单利模式 使用场景: + Python的logger就是一个单例模式,用以日志记录 + Windows的资源管理器是一个单例模式 + 线程池,数据库连接池等资源池一般也用单例模式 + ...
随机推荐
- Ubuntu系统的安装
在上一篇博客中,我们已经建立了一个“空白”的虚拟Ubuntu镜像,在这篇博客中,我们将介绍如何安装并进入完整的Ubuntu系统. 写在前面:不同版本的系统在安装过程中,有些操作可能会不同,但是其核心步 ...
- ubuntu基本使用
sudo nautilus xxx指定目录去打开 这个命令就是以root权限打开一个窗口,来管理文件
- git之环境配置(window+git+github)
本地安装git 下载最新版的git:https://msysgit.googlecode.com/files/Git-1.9.0-preview20140217.exe 安装步骤:http://jin ...
- 数位DP入门之hdu 3652 B-number
hdu 3652 B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer ...
- 利用Jquery实现http长连接(LongPoll)
参考:http://www.cnblogs.com/vagerent/archive/2010/02/05/1664450.html PS:为了满足 某些需要 实时请求的业务(PS:例如聊天室),我们 ...
- leetcode其余题目
1.Largest Rectangle in Histogram http://discuss.leetcode.com/questions/259/largest-rectangle-in-hist ...
- 数据库 - FMDB
FMDB 是基于 SQLite 封装的 面向对对象(OC) 的API. FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API FMDB 需要libsqli ...
- JavaEE下载文件名不显示中文的问题
我们在做JavaEE项目下载文件时,在我们熟悉的UTF-8编码下经常会发现文件名中文乱码.中文不显示等状况,此时,将文 件名改一下编码或许会解决这个烦恼: fileName = new String( ...
- MAVEN:::::: maven-dependency-plugin (goals "copy-dependencies", "unpack") is not supported
zhuan:http://elan1986.iteye.com/blog/1537967 <!--add by wangquanjun 20140529--> < ...
- ThreadLocal学习
1.简介: 类ThreadLocal<T>,为变量提供了线程本地化副本.对于用ThreadLocal维护的变量,当前线程中的副本不同于它在其他线程中的副本,每个线程通过ThreadLoca ...