浅析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自动化测试不是一件困难的任务.你 ...
随机推荐
- kFreeBsd 国内开源镜像站汇总
从http://bbs.chinaunix.net/archiver/tid-3756178.html这里抽取了debian源中支撑kfreebsd架构的源. 中科大: http://debian.u ...
- 记录php日志
1.记录PHP错误日志 display_errors与log_errors的区别 display_errors 错误回显,一般常用于开发模式,但是很多应用在正式环境中也忘记了关闭此选项.错误回显可以暴 ...
- Maven的安装使用以及 Maven+Spring hello world example
关于Maven Maven是一个用于项目构建的工具,通过它便捷的管理项目的生命周期.即项目的jar包依赖,开发,测试,发布打包. 做过.NET的人应该会联想到Nuget,是的Maven其实就是java ...
- 缓存技术比拼:Redis与Memcached的同与不同
转至:http://developer.51cto.com/art/201603/507980.htm 在今天的文章中,我们将探讨Redis(REmote DIctionary Server).Red ...
- margin和padding对行内元素的影响
这个是在面试的时候,面试官问我的一个小问题 自己没有考虑过inline元素设置margin和padding的问题 学习的过程记录下来 1)inline元素的高度是由元素的内容决定的(字体的大小和行高) ...
- js判断客户端平台
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mac下用ruby安装sass && webstorm下给scss文件添加watch
1.安装rvm 先安装 [Xcode](http://developer.apple.com/xcode/) 开发工具,它将帮你安装好 Unix 环境需要的开发包 sudo curl -L https ...
- SharePoint 中关于event receivers的讨论
今天一早,跟几个小伙伴在群里讨论了有关事件触发器的东西,感觉收获颇多,拿出来和大家分享.讨论的内容,主要就是关于事件触发器的同步/异步的设置以及作用. 其实接触SharePoint颇久,对于事件触发器 ...
- Step by step configuration of Outgoing Emails from SharePoint to Microsoft Online
First of all your SharePoint server should be added to Microsoft online safe sender list, so that Sh ...
- 【原】画流程图工具visio使用技巧汇总
最近写论文需要画不少流程图,有两种选择,一是word, 二是visio.原先一直用word画,效果也还可以,但是每个部件画完后为了便于适应排版变动,需要将需要的模块按下ctrl逐个点击选中后进行组合. ...