浅析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自动化测试不是一件困难的任务.你 ...
随机推荐
- SignalR-入门
1.什么是SignalR: ASP.NET SignalR是为简化开发开发人员将实时web内容添加到应用程序过程而提供的类库.实时web功能指的是让服务器代码可以随时主动推送内容给客户端,而不是让服务 ...
- ASP.NET Web API 通过Authentication特性来实现身份认证
using System; using System.Collections.Generic; using System.Net.Http.Headers; using System.Security ...
- [Angularjs]视图和路由(四)
写在前面 关于angularjs的路由的概念基本上这篇就要结束了,通过学习,以及在实际项目中的实践,还是比较容易上手的.自己也通过angularjs做了一个在app上的一个模块,效果还是可以的. 系列 ...
- Angular框架
Angular 框架 Angular介绍 库和框架的区别 jQuery:库 库一般都是封装了一些常用的方法 自己手动去调用这些方法,来完成我们的功能 code $('#txt').val('我是小明' ...
- JavaScript基础10——node对象
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Web安全开发注意事项
1.sql注入:这个很常规了,不要拼字符串以及过滤关键字都可以防住,需要注意的是,Cookie提交的参 数也是可以导致注入漏洞的.2.旁注:就是说在保证自己的程序没问题的同时,也要保证同台服务器的其他 ...
- GridView总结一:GridView自带分页及与DropDownList结合使用
GridView自带的分页功能实现: 要实现GrdView分页的功能 操作如下: 1.更改GrdView控件的AllowPaging属性为true. 2.更改GrdView控件的PageSize属性为 ...
- 发布的时候Archive灰色
主要是因为发布的时候要选为将模拟器选择一下,选为Generic iOS Device. 来自为知笔记(Wiz)
- 全球最低功耗蓝牙单芯片DA14580的软件体系 -RW内核和消息处理机制
上一篇文章<蓝牙单芯片DA14580的硬件架构和低功耗>阐述了DA14580的硬件架构和低功耗的工作原理.本文文章阐述该平台的软件体系,并着重分析消息事件的处理机制. 一.DA14580S ...
- 优于CoreData的Realm数据库基础教程
Realm 是一个跨平台的移动数据库引擎,于 2014 年 7 月发布,准确来说,它是专门为移动应用所设计的数据持久化解决方案之一. Realm 可以轻松地移植到您的项目当中,并且绝大部分常用的功能( ...