先来看两段代码

代码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模式的更多相关文章

  1. 浅谈MVVM模式和MVP模式——Vue.js向

    浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...

  2. iOS:个人浅谈工厂模式

    一.什么是工厂方法? 正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟到子类中进行.工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好 ...

  3. 浅谈MVC模式

    MVC模式(三层架构模式) (Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  4. 设计模式浅谈----策略模式(c#及java实现)

    一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...

  5. 浅谈MVC模式与MVVM模式的区别

    MVC模式: M:Model(数据模型),用于存放数据 V:View(视图),也就是用户界面 C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给V ...

  6. Swift语言精要 - 浅谈代理模式(Delegate)

    在iOS编程中,我们经常谈到代理代理,也就是delegate,那么什么是代理呢? 我们来看一下cocoa对它的描述: Delegation is Cocoa’s term for passing of ...

  7. 设计模式之——浅谈strategy模式(策略模式)

    strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...

  8. 浅谈ThreadLocal模式

    一.前言: ThreadLocal模式,严格意义上不是一种设计模式,而是java中解决多线程数据共享问题的一个方案.ThreadLocal类是java JDK中提供的一个类,用来解决线程安全问题,并不 ...

  9. 浅谈单利模式及其应用场景(Python)

    python 中的单利模式 使用场景: + Python的logger就是一个单例模式,用以日志记录 + Windows的资源管理器是一个单例模式 + 线程池,数据库连接池等资源池一般也用单例模式 + ...

随机推荐

  1. linux采用模块方法,添加一个新的设备

    该文转载自:http://rangercyh.blog.51cto.com/1444712/521244 系统调用是操作系统内核和应用程序之间的接口,而设备驱动程序是操作系统内核和机器硬件之间的接口. ...

  2. erlang 练手 进程环

    Erlang 编程指南第四章 练习4-2 编写一个程序,生成N个进程并相连成环,启动环后绕环发送M个消息,当收到退出消息后终止. ringStart(M,N,Message, Cp) -> io ...

  3. 【实习记】2014-09-26恢复linux下误删的ntfs盘中的文件

        情景,ubuntu下把NTFS格式的盘中的“实习记”文件夹彻底删除了,追毁莫及,粗心觉不是一件好的事情. linux下回复ntfs盘下的文件不能用ext3grep,而使用debugfs命令实在 ...

  4. Php之Http请求urlencode/rawurlencode

    在http请求中,如果参数值带中文最好使用urlencode/rawurlencode函数. 如果参数值中带加号也最好使用,否则后台接收时,+号变成空格,引起不必要的麻烦. 注:urlencode和r ...

  5. Shell脚本——DNS自动部署

    详细说明查看: (一)跟我一起玩Linux网络服务:DNS服务——BIND(/etc/named.conf./var/named)设置实现和解释 #! /bin/bash IP="10.10 ...

  6. Web模板引擎本质前奏

    执行字符串表示的函数,并为该函数提供全局变量: #! /usr/bin/env python3 namespace = {'name': 'zingp', 'data': [16, 19, 25]} ...

  7. letcode刷题之两数相加

    letcode里面刷题,坑还是链表不熟,(1)头结点还是有必要设置,否则返回的时候找不到位置:(2)先设置next到新节点再next到下一个节点:都是基础知识 /* * * You are given ...

  8. Sqlserver 原生 MD5 函数(转)

    --创建md5函数CREATE FUNCTION [dbo].[MD5](@src varchar(255) )RETURNS varchar(255)ASBEGIN    DECLARE @md5 ...

  9. POJ 1442 Black Box 堆

    题目: http://poj.org/problem?id=1442 开始用二叉排序树写的,TLE了,改成优先队列,过了.. 两个版本都贴一下吧,赚稿费.. #include <stdio.h& ...

  10. javascript第二遍基础学习笔记(二)

    一.操作符 1.一元操作符: 自加自减(分前置和后置2种):++.-- 区别:前置的先自加或自减,后进行计算:而后置的是先进行计算,后自加或自减(在其会产生负面影响时才能体现区别): ; i++; / ...