selenium目前比较流行的设计模式就是page object,那么到底什么是page object呢,简单来说,就是把页面作为对象,在使用中传递页面对象,来使用页面对象中相应的成员或者方法,能更好的提现java的面向对象和封装特性,首先看一下官网的解释:

Page Object Design Pattern

Page Object is a Design Pattern which has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to interact with the UI of that page. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Subsequently all changes to support that new UI are located in one place.

The Page Object Design Pattern provides the following advantages

1. There is a clean separation between test code and page specific code such as locators (or their use if you’re using a UI Map) and layout.

2. There is a single repository for the services or operations offered by the page rather than having these services scattered throughout the tests.

In both cases this allows any modifications required due to UI changes to all be made in one place. Useful information on this technique can be found on numerous blogs as this ‘test design pattern’ is becoming widely used. We encourage the reader who wishes to know more to search the internet for blogs on this subject. Many have written on this design pattern and can provide useful tips beyond the scope of this user guide. To get you started, though, we’ll illustrate page objects with a simple example.

First, consider an example, typical of test automation, that does not use a page object.

/***
* Tests login feature
*/
public class Login { public void testLogin() {
selenium.type("inputBox", "testUser");
selenium.type("password", "my supersecret password");
selenium.click("sign-in");
selenium.waitForPageToLoad("PageWaitPeriod");
Assert.assertTrue(selenium.isElementPresent("compose button"),
"Login was unsuccessful");
}
}

There are two problems with this approach.

  1. There is no separation between the test method and the AUT’s locators (IDs in this example); both are intertwined in a single method. If the AUT’s UI changes its identifiers, layout, or how a login is input and processed, the test itself must change.
  2. The ID-locators would be spread in multiple tests, in all tests that had to use this login page.

Applying the page object techniques, this example could be rewritten like this in the following example of a page object for a Sign-in page.

/**
* Page Object encapsulates the Sign-in page.
*/
public class SignInPage { private Selenium selenium; public SignInPage(Selenium selenium) {
this.selenium = selenium;
if(!selenium.getTitle().equals("Sign in page")) {
throw new IllegalStateException("This is not sign in page, current page is: "
+selenium.getLocation());
}
} /**
* Login as valid user
*
* @param userName
* @param password
* @return HomePage object
*/
public HomePage loginValidUser(String userName, String password) {
selenium.type("usernamefield", userName);
selenium.type("passwordfield", password);
selenium.click("sign-in");
selenium.waitForPageToLoad("waitPeriod"); return new HomePage(selenium);
}
}

and page object for a Home page could look like this.

/**
* Page Object encapsulates the Home Page
*/
public class HomePage { private Selenium selenium; public HomePage(Selenium selenium) {
if (!selenium.getTitle().equals("Home Page of logged in user")) {
throw new IllegalStateException("This is not Home Page of logged in user, current page" +
"is: " +selenium.getLocation());
}
} public HomePage manageProfile() {
// Page encapsulation to manage profile functionality
return new HomePage(selenium);
} /*More methods offering the services represented by Home Page
of Logged User. These methods in turn might return more Page Objects
for example click on Compose mail button could return ComposeMail class object*/ }

So now, the login test would use these two page objects as follows.

/***
* Tests login feature
*/
public class TestLogin { public void testLogin() {
SignInPage signInPage = new SignInPage(selenium);
HomePage homePage = signInPage.loginValidUser("userName", "password");
Assert.assertTrue(selenium.isElementPresent("compose button"),
"Login was unsuccessful");
}
}

官网中使用的代码例子是selenium1的方式,为了方便我使用webdirver做了实现,并使用知乎登录作为例子。

思路:

A:打开浏览器

B:访问www.zhihu.com

C:登录

D:登录后,主页验证是否登录成功

以上四个步骤用到了2个页面,登录页面和主页,下面我们就对这两个页面进行封装。

1.新建一个HomePage类。

package com.pageobject1;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert; /**
* @author QiaoJiafei
* @version 创建时间:2016年2月26日 上午10:01:51
* 类说明
*/
public class HomePage {
private WebDriver driver;
WebElement element_account; public HomePage(WebDriver driver) {
if(!driver.getTitle().equals("首页 - 知乎")) {
throw new IllegalStateException("This is not Home Page of logged in user, current page" +
"is: " +driver.getTitle());
}
element_account = driver.findElement(By.id(":0"));
} public HomePage manageProfile() {
// Page encapsulation to manage profile functionality
String text = element_account.getText();
Assert.assertEquals(text, "乔叶叶");
return new HomePage(driver);
}
  public XXXpage clickhrep() {
  //点击某个链接的方法,并返回跳转后的页面对象
  
  return XXXpage(driver);
}
}

2.新建一个LoginPage类

package com.pageobject1;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait; import com.google.common.base.Predicate; /**
* @author QiaoJiafei
* @version 创建时间:2016年2月26日 上午9:55:23
* 类说明
*/
public class LoginPage { private WebDriver driver;
WebElement element_username;
WebElement element_password;
WebElement element_submit; public LoginPage(WebDriver driver) {
// TODO Auto-generated constructor stub
this.driver = driver;
if(!driver.getTitle().equals("知乎 - 与世界分享你的知识、经验和见解")) {
throw new IllegalStateException("This is not sign in page, current page is: "
+driver.getTitle());
}
element_username = driver.findElement(By.name("account"));
element_password = driver.findElement(By.name("password"));
element_submit = driver.findElement(By.xpath("/html/body/div[1]/div/div[2]/div[2]/form/div[3]/button"));
}
public HomePage loginValidUser(String userName, String password) {
element_username.sendKeys(userName);
element_password.sendKeys(password);
element_submit.click();
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(new ExpectedCondition<WebElement>(){ @Override
public WebElement apply(WebDriver arg0) {
// TODO Auto-generated method stub
return arg0.findElement(By.id(":0"));
} }).isDisplayed();
     //注意根据实际业务,返回相应页面对象
return new HomePage(driver);
}
}

3.新建一个测试类

package com.pageobject1;

import java.sql.Driver;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; /**
* @author QiaoJiafei
* @version 创建时间:2016年2月26日 上午10:20:29
* 类说明
*/
public class TestLogin {
WebDriver driver = null;
@BeforeClass
public void beforeClass() {
String key = "webdriver.firefox.bin";
String value = "C:/Program Files (x86)/Mozilla Firefox/firefox.exe";
System.setProperty(key, value);
driver = new FirefoxDriver(); driver.manage().window().maximize();
driver.get("https://www.zhihu.com/#signin");
} @AfterClass
public void afterClass() {
driver.quit();
} @Test
public void testLogin() { LoginPage loginPage = new LoginPage(driver);
HomePage homePage = loginPage.loginValidUser("XXXXX@163.com", "XXXXX");
/*
* 下面就可以使用homepage对象来做操作,如:
* homePage.manageProfile();
*
* */
Assert.assertEquals(driver.getTitle(), "首页 - 知乎");
}
}

由此可见,在测试类中,操作的基本都是页面对象,逻辑清晰,代码简单,在后期的维护中,如果那个页面的元素发生变化,则只需要更改相应页的页面类即可,不需要更改测试类的逻辑。

看到这里有的也许会问:每次都要求返回一个页面对象,有时不确定怎么办?

我的解决办法是:在实际的自动化测试中,是先有测试用例,后编写测试脚本,所以基本每个页面传递对象都可以确定,如在主页我点击一篇文章会跳转一个文章页面,点击个人头像灰跳转一个个人页面,在就是在主页类中写两个方法,一个方法返回文章页面,一个方法返回个人页面,依次类推……

好了,这篇文件就先简单介绍一下page object的设计思想及用法,以后会写一篇文章,如何在框架中使用这种模式

浅析selenium的page object模式的更多相关文章

  1. selenium page object模式

    页面对象模式将测试代码和被测试页面的元素及操作进行分离,以降低页面元素的变化对测试代码的影响.每个被测试的页面都会被定义一个类,类中会定位元素和操作. 如果不使用page object模式,则相同的操 ...

  2. 【C#|.NET】从细节出发(三) 逻辑层事务和page object模式

    一. 业务逻辑层的事务问题 如果你的程序分层清晰并且系统禁用复杂存储过程,那么在DA中的职责比较单一.程序的逻辑通过BLL调用各种不同模块的DA来实现数据操作.如果当需要不同模块在一个事务的时候,问题 ...

  3. Python+Selenium使用Page Object实现页面自动化测试

    Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...

  4. Selenium+java - Page Object设计模式

    前言 Page Object(页面对象)模式,是Selenium实战中最为流行,并且被自动化测试同学所熟悉和推崇的一种设计模式之一.在设计测试时,把页面元素定位和元素操作方法按照页面抽象出来,分离成一 ...

  5. 转 Page Object模式

    Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...

  6. UI自动化测试的Page Object模式

    在UI级的自动化测试框架中,当页面样式改变或者页面元素属性改变,那么代码也要随之进行修改,如何做到高效快速的修改代码来适应这些改变呢,这个时候可以引入Page Object模式,也是页面对象设计模式. ...

  7. python+selenium自动化软件测试(第7章):Page Object模式

    什么是Page ObjectModel模式Page Objects是selenium的一种测试设计模式,主要将每个页面看作是一个class.class的内容主要包括属性和方法,属性不难理解,就是这个页 ...

  8. 使用page object模式抓取几个主要城市的pm2.5并从小到大排序后写入txt文档

    #coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...

  9. Page Object 模式编写UiAutomator脚本

    在我们学习Page Object Model之前,我们先了解一下Page Object Model(以下简称POM). 为什么要POM 用UiAutomator启动UI自动化测试不是一件困难的任务.你 ...

随机推荐

  1. ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表

    本篇文章将介绍区域报表和页面报表的常见使用场景.区别和选择报表类型的一些建议,两种报表的模板设计.数据源(设计时和运行时)设置.和浏览报表的区别. ActiveReports 报表控件官方中文入门教程 ...

  2. CentOS7 Debian 8 安装VMware-tools

    如在安装过程中碰到未找到gcc 或者 kernel headers的可按以下方案解决,适用任意版本 CentOS 7 1. Update the kernel: $ yum update kernel ...

  3. Java中处理异常中return关键字

    Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...

  4. API的非向后兼容性无论如何通常代表着一种比较差的设计

    不管一个类库或者工具方法实现多么的好,如果无法做到向后兼容性,通常会给用户带来很大的升级成本,很多对此的依赖如果希望在后续的升级和维护期间使用该类库的其他新增特性或者好处,将不得不推迟升级亦或是被迫接 ...

  5. Web前端小白入门指迷

    前注:这篇文章首发于我自己创办的服务于校园的技术分享 [西邮 Upper -- 004]Web前端小白入门指迷,写得很用心也就发在这里. 大前端之旅 大前端有很多种,Shell 前端,客户端前端,Ap ...

  6. ThoughtWorks西邮暑期特训营 -- JavaScript在线笔试题

    ThoughtWorks 公司在西邮正式开办的只教女生前端开发的女子卓越实验室已经几个月过去了,这次计划于暑期在西邮内部开展面向所有性别所有专业的前端培训. 具体官方安排请戳:ThoughtWorks ...

  7. C# Sqlite事务

    在 C#中执行Sqlite数据库事务有两种方式:Sql代码和C#代码 1.Sql代码: BEGIN… COMMIT /ROLLBACK 2.C#代码: using (SQLiteConnection ...

  8. C# Sqlite 序列

    sqlite 不能直接创建自定义函数,不能像 sql server中那样方便创建并使用.不过我们照样可以创建它,创建成功后,我们照样可以随心所欲(比如批量更新等) 序列是一个数据库中很常用的操作,在其 ...

  9. CSS Hack(转)

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...

  10. 通过重写OnScrollListener来监听RecyclerView是否滑动到底部

    为了增加复用性和灵活性,我们还是定义一个接口来做监听滚动到底部的回调,这样你就可以把它用在listview,scrollView中去. OnBottomListener package kale.co ...