做自动化框架,不可避免的就是对象库。

有一个好的对象库,可以让整个测试体系:

  • 更容易维护
  • 大大增加代码重用
  • 增加测试系统的稳定性

这里先了解一下我所说的对象库:

所谓的页面对象,是指每一个真是的页面是一个对象。

比如zhihu的登陆页面是一个页面对象,http://www.zhihu.com/#signin

这个页面对象主要包含一个输入邮箱的输入框(一个元素对象),一个输入密码的密码框

一个登陆框。当然,zhihu不止一个页面,有无数页面,每一个页面都可以封装为一个对象。而每个

页面的元素,也可以封装成一个个元素对象。

为什么要封装成一个个对象?

还是以这个登陆页面为例,如果有一天zhihu改版,登陆界面UI变了,(但是需要输入用户名和密码还有登陆按钮不会消失吧)。

登陆页面的元素的位置也相应改变,如果你的测试用例没有封装过页面和元素, 每个页面都是拿webdriver 直接写,页面元素定位

也分布到测试用例中,这要维护起来要全部改掉测试用例。如果你封装了页面,封装了元素,再封装一个对应的登陆Action,你的每个

测试用例是调用的login.action()。  这样,你只需要改变你对象库的内容就完美解决UI变化,而不必一个个修改测试用例。

测试框架目录如下:

接下来一这个登陆为例:

首先封装一个BasePage的类,毕竟所有的页面都有共同的东西,每个页面都有元素,每个页面元素都有相应的方法

这里简单封装了几个方法,如type

package com.dbyl.libarary.utils;

import java.io.IOException;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait; public class BasePage { protected WebDriver driver;
protected String[][] locatorMap; protected BasePage(WebDriver driver) throws IOException {
this.driver = driver;
locatorMap = ReadExcelUtil.getLocatorMap();
} protected void type(Locator locator, String values) throws Exception {
WebElement e = findElement(driver, locator);
e.sendKeys(values);
} protected void click(Locator locator) throws Exception {
WebElement e = findElement(driver, locator);
e.click();
} protected void clickAndHold(Locator locator) throws IOException {
WebElement e = findElement(driver, locator);
Actions actions = new Actions(driver);
actions.clickAndHold(e).perform();
} public WebDriver getDriver() {
return driver;
} public void setDriver(WebDriver driver) {
this.driver = driver;
} public WebElement getElement(Locator locator) throws IOException {
return getElement(this.getDriver(), locator);
} /**
* get by parameter
*
* @author Young
* @param driver
* @param locator
* @return
* @throws IOException
*/
public WebElement getElement(WebDriver driver, Locator locator)
throws IOException {
locator = getLocator(locator.getElement());
WebElement e;
switch (locator.getBy()) {
case xpath:
e = driver.findElement(By.xpath(locator.getElement()));
break;
case id:
e = driver.findElement(By.id(locator.getElement()));
break;
case name:
e = driver.findElement(By.name(locator.getElement()));
break;
case cssSelector:
e = driver.findElement(By.cssSelector(locator.getElement()));
break;
case className:
e = driver.findElement(By.className(locator.getElement()));
break;
case tagName:
e = driver.findElement(By.tagName(locator.getElement()));
break;
case linkText:
e = driver.findElement(By.linkText(locator.getElement()));
break;
case partialLinkText:
e = driver.findElement(By.partialLinkText(locator.getElement()));
break;
default:
e = driver.findElement(By.id(locator.getElement()));
}
return e;
} public boolean isElementPresent(WebDriver driver, Locator myLocator,
int timeOut) throws IOException {
final Locator locator = getLocator(myLocator.getElement());
boolean isPresent = false;
WebDriverWait wait = new WebDriverWait(driver, 60);
isPresent = wait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver d) {
return findElement(d, locator);
}
}).isDisplayed();
return isPresent;
} /**
* This Method for check isPresent Locator
*
* @param locator
* @param timeOut
* @return
* @throws IOException
*/
public boolean isElementPresent(Locator locator, int timeOut)
throws IOException {
return isElementPresent(driver,locator, timeOut);
} /**
*
* @param driver
* @param locator
* @return
*/
public WebElement findElement(WebDriver driver, final Locator locator) {
WebElement element = (new WebDriverWait(driver, locator.getWaitSec()))
.until(new ExpectedCondition<WebElement>() { @Override
public WebElement apply(WebDriver driver) {
try {
return getElement(driver, locator);
} catch (IOException e) {
// TODO Auto-generated catch block
return null;
} } });
return element; } public Locator getLocator(String locatorName) throws IOException { Locator locator;
for (int i = 0; i < locatorMap.length; i++) {
if (locatorMap[i][0].endsWith(locatorName)) {
return locator = new Locator(locatorMap[i][1]);
}
} return locator = new Locator(locatorName); }
}

接下来封装元素,Webdriver的元素,每个元素都有相应的定位地址(xpath路径或css或id)等待时间和定位类型,默认为By.xpath

package com.dbyl.libarary.utils;

/**
* This is for element library
*
* @author Young
*
*/
public class Locator {
private String element; private int waitSec; /**
* create a enum variable for By
*
* @author Young
*
*/
public enum ByType {
xpath, id, linkText, name, className, cssSelector, partialLinkText, tagName
} private ByType byType; public Locator() { } /**
* defaut Locator ,use Xpath
*
* @author Young
* @param element
*/
public Locator(String element) {
this.element = element;
this.waitSec = 3;
this.byType = ByType.xpath;
} public Locator(String element, int waitSec) {
this.waitSec = waitSec;
this.element = element;
this.byType = ByType.xpath;
} public Locator(String element, int waitSec, ByType byType) {
this.waitSec = waitSec;
this.element = element;
this.byType = byType;
} public String getElement() {
return element;
} public int getWaitSec() {
return waitSec;
} public ByType getBy() {
return byType;
} public void setBy(ByType byType) {
this.byType = byType;
} }

接下来就是登陆页面的类,这个登陆页面的元素,放在excel统一管理,要获取元素的信息,首先从excel读取。

读取excel的页面元素是使用POI开源框架

package com.dbyl.libarary.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; public class ReadExcelUtil { static String path; /**
* @author Young
* @return
* @throws IOException
*/
public static String[][] getLocatorMap() throws IOException {
path = "C:/Users/Young/workspace/Demo/src/com/dbyl/libarary/pageAction/UILibrary.xls";
File f1 = new File(path);
FileInputStream in = new FileInputStream(f1);
HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(in));
Sheet sheet = wb.getSheetAt(0);
Row header = sheet.getRow(0);
String[][] locatorMap = new String[sheet.getLastRowNum() + 1][header
.getLastCellNum()];
for (int rownum = 0; rownum <= sheet.getLastRowNum(); rownum++) {
// for (Cell cell : row)
Row row = sheet.getRow(rownum); if (row == null) { continue; }
String value;
for (int cellnum = 0; cellnum <= row.getLastCellNum(); cellnum++) {
Cell cell = row.getCell(cellnum);
if (cell == null) {
continue;
} else {
value = "";
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
value = cell.getDateCellValue().toString(); } else {
value = Double.toString((int) cell
.getNumericCellValue()); }
break;
case Cell.CELL_TYPE_BOOLEAN:
value = Boolean.toString(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
value = cell.getCellFormula().toLowerCase();
break;
default:
value = " ";
System.out.println();
}
locatorMap[rownum][cellnum] = value; }
}
in.close();
wb.close(); return locatorMap;
} }

页面类

package com.dbyl.libarary.pageAction;

import java.io.IOException;
import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import com.dbyl.libarary.utils.BasePage;
import com.dbyl.libarary.utils.Locator; public class LoginPage extends BasePage { WebDriver driver; public WebDriver getDriver() {
return driver;
} public LoginPage(WebDriver driver) throws IOException {
super(driver);
driver.get("http://www.zhihu.com/#signin");
} Locator loginEmailInputBox = new Locator("loginEmailInputBox"); Locator loginPasswordInputBox = new Locator("loginPasswordInputBox");
Locator loginButton = new Locator("loginButton");
Locator profile = new Locator(
"profile"); public void typeEmailInputBox(String email) throws Exception {
type(loginEmailInputBox, email);
} public void typePasswordInputBox(String password) throws Exception {
type(loginPasswordInputBox, password);
} public void clickOnLoginButton() throws Exception {
click(loginButton);
} public boolean isPrestentProfile() throws IOException {
return isElementPresent(profile, 20); } public void waitForPageLoad() {
super.getDriver().manage().timeouts()
.pageLoadTimeout(30, TimeUnit.SECONDS);
} }

接下来就是登陆的Action

package com.dbyl.libarary.action;

import org.openqa.selenium.WebDriver;
import org.testng.Assert; import com.dbyl.libarary.pageAction.HomePage;
import com.dbyl.libarary.pageAction.LoginPage; public class CommonLogin { private static WebDriver driver; public static WebDriver getDriver() {
return driver;
} static LoginPage loginPage; public static HomePage login(String email, String password)
throws Exception {
loginPage = new LoginPage(getDriver());
loginPage.waitForPageLoad();
loginPage.typeEmailInputBox(email);
loginPage.typePasswordInputBox(password);
loginPage.clickOnLoginButton();
Assert.assertTrue(loginPage.isPrestentProfile(), "login failed");
return new HomePage(getDriver());
} public static HomePage login() throws Exception {
return CommonLogin.login("seleniumcookies@126.com", "cookies123");
} public static void setDriver(WebDriver driver) {
CommonLogin.driver = driver;
} }

至此为止,已经封装完毕

接下来就能在测试用例直接调用者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.dbyl.tests;
 
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
 
import com.dbyl.libarary.action.ViewHomePage;
import com.dbyl.libarary.utils.DriverFactory;
import com.dbyl.libarary.utils.UITest;
 
public class loginTest extends UITest{
 
 
    WebDriver driver=DriverFactory.getChromeDriver();
    @BeforeMethod(alwaysRun=true)
    public void init()
    {
        super.init(driver);
        ViewHomePage.setDriver(driver);
        //CommonLogin.setDriver(driver);
    }
    @Test(groups="loginTest")
    public void loginByUerName() throws Exception
    {
        //CommonLogin.login("seleniumcookies@126.com","cookies123");
        ViewHomePage.viewMyProfile();
    }
 
    @AfterMethod(alwaysRun=true)
    public void stop() {
        super.stop();
    }         
}

  

demo的下载地址:https://github.com/tobecrazy/Demo

selenium测试框架篇的更多相关文章

  1. selenium测试框架篇,页面对象和元素对象的管理

    前期已经做好使用Jenkins做buildhttp://www.cnblogs.com/tobecrazy/p/4529399.html 做自动化框架,不可避免的就是对象库. 有一个好的对象库,可以让 ...

  2. selenium测试框架使用xml作为对象库

    之前已经写过一篇: selenium测试框架篇,页面对象和元素对象的管理 上次使用的excel作为Locator对象管理,由于excel处理不够方便,有以下缺点: 不能实现分page 加载Locato ...

  3. selenium 测试框架中使用grid

    之前的测试框架:http://www.cnblogs.com/tobecrazy/p/4553444.html 配合Jenkins可持续集成:http://www.cnblogs.com/tobecr ...

  4. 『心善渊』Selenium3.0基础 — 2、Selenium测试框架环境搭建(Windows)

    目录 1.浏览器安装 2.浏览器驱动下载 (1)ChromeDriver for Chrome (2)Geckodriver for Firefox (3)IEDriverServer for IE ...

  5. 《Selenium自动化测试实战:基于Python》Selenium自动化测试框架入门

    第1章  Selenium自动化测试框架入门 1.1  Selenium自动化测试框架概述 说到目前流行的自动化测试工具,相信只要做过软件测试相关工作,就一定听说过Selenium. 图1-1是某企业 ...

  6. 《手把手教你》系列基础篇(七十七)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 上篇(详解教程)

    1.简介 今天主要是讲解和分享:TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用dependsOnMethods,testNG会自动根据@Test方法名称 ...

  7. 《手把手教你》系列基础篇(七十八)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 中篇(详解教程)

    1.简介 上一篇讲解了依赖测试的各种方法,今天继续讲解依赖测试的方法,这一篇主要是讲解和分享通过xml文件配置组名依赖方法( 主要是测试组的用法).废话不说,直接上干货. 2.实例 测试组:一个组可包 ...

  8. 《手把手教你》系列基础篇(八十)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试-番外篇(详解教程)

    1.简介 经过前边几篇知识点的介绍,今天宏哥就在实际测试中应用一下前边所学的依赖测试.这一篇主要介绍在TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用de ...

  9. Selenium 4 Java的最佳测试框架

    几十年来,Java一直是开发应用程序服务器端的首选编程语言.尽管JUnit一直在与开发人员一起帮助他们进行自动化的单元测试,但随着时间的推移和测试行业的发展,特别是伴随着自动化测试的兴起,已经开发了许 ...

随机推荐

  1. Java使用FileLock实现Java进程互斥锁

    原理:JDK的nio包中FileLock实现类似Linux fcntl的文件锁, 可使文件被进程互斥访问.  借助此功能, 可以实现强大的Java进程互斥锁, 从而在应用层面保证同一时间只有惟一的Ja ...

  2. Go语言工程结构

    Go是一门推崇软件工程理念的编程语言. Go的代码必须放在GOPATH目录下,它应该包含三个子目录: src:用于以代码包的形式组织并保存Go源码文件.应该分为三类:库源码文件.命令源码文件.测试源码 ...

  3. Node.js深受欢迎的六大原因

    Node.js是一种后起的优秀服务器编程语言,它用来构建和运行Web应用,这和ASP.NET,Ruby on Rails或Spring框架做的工作是类似的.它使用JavaScript作为主要的开发语言 ...

  4. NSKeyValueObserving(KVO)

    NSKeyValueObserving非正式协议定义了一种机制,它允许对象去监听其它对象的某个属性的修改. 我们可以监听一个对象的属性,包括简单属性,一对一的关系,和一对多的关系.一对多关系的监听者会 ...

  5. Implementation Documentation[转]

    原文地址:http://prasanna-adf.blogspot.tw/2009/04/implementation-documentation.html Following are the lis ...

  6. cacti install on ubuntu

    安装cacti需要的软件需要 nginx + php + mysql + rrdtool + cacti + snmp 1.nginx 安装配置 首先按照如下命令安装,明显是马虎不细心./config ...

  7. Jquery方法的应用

    <body> <div id="one"><span>one</span></div><div class=&qu ...

  8. 使用HTML5中postMessage实现Ajax中的POST跨域问题

    HTML5中提供了在网页文档之间相互接收与发送信息的功能.使用这个功能,只要获取到网页所在窗口对象的实例,不仅仅同源(域+端口号)的web网页之间可以互相通信,甚至可以实现跨域通信. 浏览器支持程度: ...

  9. GS连接事件

    GS网络连接事件 //网络事件 //这个事件是在libevent里面的收到的事件就是在那个listen里面,就是客户端打开,服务器收到通知 link_stat stat = (link_stat)rP ...

  10. VS Bug 当获取其他项目的代码时, F5 无法进入调试模式. 也不报错....

    在64位的机子下, 被获用的项目使用X86时会出现. 就会出现   F5 无法进入调试模式. 也不报错.... 打断点也没有用. 在不加入X86项目的代码时, 又可以运行..   解决方案:   检查 ...