浅析selenium的page object模式
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.
- 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.
- 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模式的更多相关文章
- selenium page object模式
页面对象模式将测试代码和被测试页面的元素及操作进行分离,以降低页面元素的变化对测试代码的影响.每个被测试的页面都会被定义一个类,类中会定位元素和操作. 如果不使用page object模式,则相同的操 ...
- 【C#|.NET】从细节出发(三) 逻辑层事务和page object模式
一. 业务逻辑层的事务问题 如果你的程序分层清晰并且系统禁用复杂存储过程,那么在DA中的职责比较单一.程序的逻辑通过BLL调用各种不同模块的DA来实现数据操作.如果当需要不同模块在一个事务的时候,问题 ...
- Python+Selenium使用Page Object实现页面自动化测试
Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...
- Selenium+java - Page Object设计模式
前言 Page Object(页面对象)模式,是Selenium实战中最为流行,并且被自动化测试同学所熟悉和推崇的一种设计模式之一.在设计测试时,把页面元素定位和元素操作方法按照页面抽象出来,分离成一 ...
- 转 Page Object模式
Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...
- UI自动化测试的Page Object模式
在UI级的自动化测试框架中,当页面样式改变或者页面元素属性改变,那么代码也要随之进行修改,如何做到高效快速的修改代码来适应这些改变呢,这个时候可以引入Page Object模式,也是页面对象设计模式. ...
- python+selenium自动化软件测试(第7章):Page Object模式
什么是Page ObjectModel模式Page Objects是selenium的一种测试设计模式,主要将每个页面看作是一个class.class的内容主要包括属性和方法,属性不难理解,就是这个页 ...
- 使用page object模式抓取几个主要城市的pm2.5并从小到大排序后写入txt文档
#coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...
- Page Object 模式编写UiAutomator脚本
在我们学习Page Object Model之前,我们先了解一下Page Object Model(以下简称POM). 为什么要POM 用UiAutomator启动UI自动化测试不是一件困难的任务.你 ...
随机推荐
- 老外还是喜欢Ubuntu的
有图为证? 开效果应该是Ubuntu的界面了,当然,不知是不是backtrack. 这里面的Hacker用的电脑都不是水果.是没有给钱么.
- mysql metadata lock锁
很多情况下,很多问题从理论上或者管理上而言都是可以避免或者说很好解决的,但是一旦涉及到现实由于管理或者协调或者规范执行的不够到位,就会出现各种各样本不该出现的问题,这些问题的通常在生产环境并不会出现, ...
- C#常用集合的使用(转载)
大多数集合都在System.Collections,System.Collections.Generic两个命名空间.其中System.Collections.Generic专门用于泛型集合. 针对特 ...
- 关于使用ResultSet ---结果集没有当前行
Resultset返回的结果集是从结果的前一句开始的,也就是说一开始的resultset是没有的,所以,一般使用的时候,需要这样子写: while( resultSet.next() ){ ...
- javascript基础系列(入门前须知)
-----------------------小历史---------------------------- javascript与java是两种语言,他们的创作公司不同,JavaScript当时是借 ...
- CSS类选择器和ID选择器
CSS类选择器和ID选择器皆允许以一种独立于文档元素的方式来指定样式,同时二者皆区分大小写. 区别如下: 第一:在同一个页面内,不允许有相同名字的id对象出现,但是允许相同名字的class 第二:当页 ...
- 复制转移sharepoint 2010 designer做的list workflow的方法
SharePoint 2010 designer做的workflow都有一个导出到visio的功能,但是如果是list workflow一般都是不可重用的,即使导出了,也是导不进目标站点或者list的 ...
- Oracle LPAD/RPAD函数在处理中文时的注意事项
首先看下Oracle官方对函数的定义: The RPAD function returns an expression, right-padded to a specified length with ...
- 桥牌笔记:Skill 4 Series A–Deal 5
南主打5C. 此牌的难点在于:如果黑桃4-2分布时,有没有打成的希望?看来黑桃.红桃.方块各1个失张无法避免? 但希望还是有的,那就是东家拿2张黑桃,并且有3张将牌. 这时庄家可以清2轮将牌,拔2轮黑 ...
- R语言学习笔记:向量
向量是R语言最基本的数据类型. 单个数值(标量)其实没有单独的数据类型,它只不过是只有一个元素的向量. x <- c(1, 2, 4, 9) x <- c(x[1:3], 88, x[4] ...