之前已经写过一篇:
selenium测试框架篇,页面对象和元素对象的管理
上次使用的excel作为Locator对象管理,由于excel处理不够方便,有以下缺点:
- 不能实现分page 加载Locator对象
- 不能够实现Locator对象重名
- 文件比较大,读写速度没有xml快
所以,重新写了使用dom4j操作xml,使用xml管理Locator对象,能够有效解决以上问题
首先,定义Locator文件
<?xml version="1.0" encoding="UTF-8"?> <map>
<!--locator of page map info -->
<page pageName="com.dbyl.libarary.pageAction.HomePage">
<!--Locator lists -->
<locator type="ByXpath" timeOut="3" value="//div[@class='top-nav-profile']//img[@class='avatar']">profile</locator>
</page>
<!--locator of page map info -->
<page pageName="com.dbyl.libarary.pageAction.LoginPage">
<!--Locator lists -->
<locator type="" timeOut="3" value="//input[@name='account' and not(@autocomplete)]">loginEmailInputBox</locator>
<locator type="ByXpath" timeOut="3" value="//button[@class='sign-button submit' and text()='登录']">loginButton</locator>
<locator type="ByXpath" timeOut="3" value="//div[@class='top-nav-profile']//img[@class='avatar']">profile</locator>
<locator type="ByXpath" timeOut="3" value="//input[@name='password' and @placeholder='密码']">loginPasswordInputBox</locator>
</page>
</map>
每一个Page对应一个真实的页面,而每一个page下的Locator对应一个真实的页面element
之前定义过的Locator类如下:
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;
} }
每一个Locator对象包含3属性 ByType 、timeOut时间和相应的xpath、id......的value
接下来需要写一个wrapper
package com.dbyl.libarary.utils; import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator; import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter; import com.dbyl.libarary.utils.Locator.ByType; public class xmlUtils { /**
* @author Young
* @param path
* @param pageName
* @return
* @throws Exception
*/
public static HashMap<String, Locator> readXMLDocument(String path,
String pageName) throws Exception {
System.out.print(pageName);
HashMap<String, Locator> locatorMap = new HashMap<String, Locator>();
locatorMap.clear();
File file = new File(path);
if (!file.exists()) {
throw new IOException("Can't find " + path);
}
SAXReader reader = new SAXReader();
Document document = reader.read(file);
Element root = document.getRootElement();
for (Iterator<?> i = root.elementIterator(); i.hasNext();) {
Element page = (Element) i.next();
if (page.attribute(0).getValue().equalsIgnoreCase(pageName)) {
System.out.println("page Info is:" + pageName);
for (Iterator<?> l = page.elementIterator(); l.hasNext();) {
String type = null;
String timeOut = "3";
String value = null;
String locatorName = null;
Element locator = (Element) l.next();
for (Iterator<?> j = locator.attributeIterator(); j
.hasNext();) {
Attribute attribute = (Attribute) j.next();
if (attribute.getName().equals("type")) {
type = attribute.getValue();
System.out.println(">>>>type " + type);
} else if (attribute.getName().equals("timeOut")) {
timeOut = attribute.getValue();
System.out.println(">>>>timeOut " + timeOut);
} else {
value = attribute.getValue();
System.out.println(">>>>value " + value);
} }
Locator temp = new Locator(value,
Integer.parseInt(timeOut), getByType(type));
locatorName = locator.getText();
System.out.println("locator Name is " + locatorName);
locatorMap.put(locatorName, temp);
}
continue;
} }
return locatorMap; } /**
* @param type
*/
public static ByType getByType(String type) {
ByType byType = ByType.xpath;
if (type == null || type.equalsIgnoreCase("xpath")) {
byType = ByType.xpath;
} else if (type.equalsIgnoreCase("id")) {
byType = ByType.id;
} else if (type.equalsIgnoreCase("linkText")) {
byType = ByType.linkText;
} else if (type.equalsIgnoreCase("name")) {
byType = ByType.name;
} else if (type.equalsIgnoreCase("className")) {
byType = ByType.className;
} else if (type.equalsIgnoreCase("cssSelector")) {
byType = ByType.cssSelector;
} else if (type.equalsIgnoreCase("partialLinkText")) {
byType = ByType.partialLinkText;
} else if (type.equalsIgnoreCase("tagName")) {
byType = ByType.tagName;
}
return byType;
} /**
* @author Young
* @throws IOException
*/
public static void writeXMLDocument() throws IOException {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"), format);
Document document = DocumentHelper.createDocument();
Element root = document.addElement("map");
root.addComment("locator of page map info");
Element page = root.addElement("page").addAttribute("pageName",
"com.dbyl.libarary.pageAction.HomePage");
page.addComment("Locator lists");
page.addElement("locator").addAttribute("type", "ByName")
.addAttribute("timeOut", "3")
.addAttribute("value", "\\\\div[@name]").addText("loginButton");
page.addElement("locator").addAttribute("type", "ById")
.addAttribute("timeOut", "3")
.addAttribute("value", "\\\\div[@id]").addText("InputButton");
writer.write(document);
writer.close();
} }
定义一个readXMLDocument 方法,返回一个hashMap用来和页面元素名字和Locator对象match起来,也算是一种关键字驱动.
传入的两个参数分别是library的路径和对应的page
那么怎么获取page的class路径?
可以通过反射机制获取:
locatorMap = xmlUtils.readXMLDocument(path,
this.getClass().getCanonicalName());
这样每次只按照page对象去加载其页面的Locator对象,而不是一次性全部加载到内存
hashMap可以通过key去获取Locator,这样也是极好的,比之前二维数组全部遍历好多了
封装一个basePage去处理Locator对象
package com.dbyl.libarary.utils; import java.io.IOException;
import java.util.HashMap; import org.openqa.selenium.Alert;
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.Select;
import org.openqa.selenium.support.ui.WebDriverWait; public class BasePage { protected WebDriver driver;
// protected String[][] locatorMap;
HashMap<String, Locator> locatorMap;
String path = "C:/Users/Young/workspace/Demo/src/com/dbyl/libarary/pageAction/UILibrary.xml";
protected Log log = new Log(this.getClass()); protected BasePage(WebDriver driver) throws Exception {
this.driver = driver;
log.debug(this.getClass().getCanonicalName());
// locatorMap = ReadExcelUtil.getLocatorMap();
locatorMap = xmlUtils.readXMLDocument(path,
this.getClass().getCanonicalName());
} protected void type(Locator locator, String values) throws Exception {
WebElement e = findElement(driver, locator);
log.info("type value is: " + values);
e.sendKeys(values);
} protected void click(Locator locator) throws Exception {
WebElement e = findElement(driver, locator);
log.info("click button");
e.click();
} protected void select(Locator locator, String value) throws Exception {
WebElement e = findElement(driver, locator);
Select select = new Select(e); try {
log.info("select by Value " + value);
select.selectByValue(value);
} catch (Exception notByValue) {
log.info("select by VisibleText " + value);
select.selectByVisibleText(value);
}
} protected void alertConfirm() {
Alert alert = driver.switchTo().alert();
try {
alert.accept();
} catch (Exception notFindAlert) {
throw notFindAlert;
}
} protected void alertDismiss() {
Alert alert = driver.switchTo().alert();
try {
alert.dismiss();
} catch (Exception notFindAlert) {
throw notFindAlert;
}
} protected String getAlertText() {
Alert alert = driver.switchTo().alert();
try {
return alert.getText();
} catch (Exception notFindAlert) {
throw notFindAlert;
}
} 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:
log.debug("find element By xpath");
e = driver.findElement(By.xpath(locator.getElement()));
break;
case id:
log.debug("find element By id");
e = driver.findElement(By.id(locator.getElement()));
break;
case name:
log.debug("find element By name");
e = driver.findElement(By.name(locator.getElement()));
break;
case cssSelector:
log.debug("find element By cssSelector");
e = driver.findElement(By.cssSelector(locator.getElement()));
break;
case className:
log.debug("find element By className");
e = driver.findElement(By.className(locator.getElement()));
break;
case tagName:
log.debug("find element By tagName");
e = driver.findElement(By.tagName(locator.getElement()));
break;
case linkText:
log.debug("find element By linkText");
e = driver.findElement(By.linkText(locator.getElement()));
break;
case partialLinkText:
log.debug("find element By 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
log.error("can't find element "
+ locator.getElement());
return null;
} } });
return element; } /**
* @author Young
*
* @param locatorName
* @return
* @throws IOException
*/
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);
locator = locatorMap.get(locatorName);
if (locator == null) {
locator = new Locator(locatorName);
}
return locator; }
}
接下来就可以在pageAction使用,如果使用页面跳转,可以使用反射机制,封装一个PageFactory,根据传入的Page类class创建对象
PageFactory如下:
package com.dbyl.libarary.utils; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import org.openqa.selenium.WebDriver; public class PageFactory {
public synchronized static Object getPage(Class<?> key,WebDriver d)
throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
String test = key.getCanonicalName();
System.out.println(test);
Class<?> clazz = Class.forName(test);
Object obj = null;
try {
Constructor<?> constructor = clazz.getConstructor(WebDriver.class);
obj = constructor.newInstance(d); } catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj; } }
使用方法:
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 (HomePage) PageFactory.getPage(HomePage.class, getDriver());
}
这样,这个框架能够实现一些基本操作,下一步还需要实现失败重试截图,配合虚拟机
下载地址:https://github.com/tobecrazy/Demo
selenium测试框架使用xml作为对象库的更多相关文章
-
selenium测试框架篇,页面对象和元素对象的管理
前期已经做好使用Jenkins做buildhttp://www.cnblogs.com/tobecrazy/p/4529399.html 做自动化框架,不可避免的就是对象库. 有一个好的对象库,可以让 ...
-
selenium测试框架篇
做自动化框架,不可避免的就是对象库. 有一个好的对象库,可以让整个测试体系: 更容易维护 大大增加代码重用 增加测试系统的稳定性 这里先了解一下我所说的对象库: 所谓的页面对象,是指每一个真是的页面是 ...
-
selenium 测试框架中使用grid
之前的测试框架:http://www.cnblogs.com/tobecrazy/p/4553444.html 配合Jenkins可持续集成:http://www.cnblogs.com/tobecr ...
-
『心善渊』Selenium3.0基础 — 2、Selenium测试框架环境搭建(Windows)
目录 1.浏览器安装 2.浏览器驱动下载 (1)ChromeDriver for Chrome (2)Geckodriver for Firefox (3)IEDriverServer for IE ...
-
python webdriver 测试框架-数据驱动xml驱动方式
数据驱动xml驱动的方式 存数据的xml文件:TestData.xml: <?xml version="1.0" encoding="utf-8"?> ...
-
《Selenium自动化测试实战:基于Python》Selenium自动化测试框架入门
第1章 Selenium自动化测试框架入门 1.1 Selenium自动化测试框架概述 说到目前流行的自动化测试工具,相信只要做过软件测试相关工作,就一定听说过Selenium. 图1-1是某企业 ...
-
Spring TestContext测试框架搭建
同样是测试,JUnit和Spring TestContext相比,Spring TestContext优势如下: 1.Spring TestContext可以手动设置测试事务回滚,不破坏数据现场 2. ...
-
python3+selenium框架设计02-自动化测试框架需要什么
什么是自动化测试框架 自动化测试框架能够提供便利给用户高效完成一些事情,比如,结构清晰开发脚本,多种方式.平台执行脚本,良好的日志和报告去跟踪脚本执行结果. 关于自动化测试框架的定义有很多,在我大致理 ...
-
Selenium 4 Python的最佳测试框架
随着Python语言的使用越来越流行,基于Python的测试自动化框架也越来越流行.在项目选择最佳框架时,开发人员和测试人员会有些无法下手.做出选择是应该判断很多事情,框架的脚本质量,测试用例的简单性 ...
随机推荐
-
RMAN还原32位数据库到64位实例的错误处理
将ORACLE 10g 32bit数据库还原到测试机ORACLE 10g 64bit的数据库实例上, 还原.恢复数据库后,使用open resetlogs打开数据库后,发现警告日志里面有ORA-120 ...
-
HTML5发布的意义
解决文档结构混乱 以前的文档结构过度依赖div,HTML5推出了多种语义化标签,使得文档更利于阅读器等理解,更利于SEO优化. 解决浏览器之间的兼容性问题 市场上浏览器种类繁多,每个浏览器厂商都在做自 ...
-
第六周博客作业<;西北师范大学|李晓婷>;
1.助教博客链接:https://home.cnblogs.com/u/lxt-/ 2.作业要求链接:https://www.cnblogs.com/nwnu-daizh/p/10569690.htm ...
-
微信小程序开发测试
微信小程序 在2017-01-09正式上线,本着跟上时代潮流的精神,写一份教程来看看 微信IDE下载地址为: 微信IDE 在windows下直接 双击 exe安装即可,安装完成后的界面如下: 得到这个 ...
-
java按照指定格式输出系统时间使用SimpleDateFormat方法
public class TimeThree { public static void main(String[] args) { SimpleDateFormat d = new SimpleDat ...
-
PHP生成四角图片
<?php /** 圆角 $radius = 100; $img = imagecreatetruecolor($radius, $radius); // 创建一个正方形的图像 $bgcolor ...
-
Hadoop Avro支持多输入AvroMultipleInputs
Avro 提供了1.x版本的AvroMultipleInputs,但是不支持2.x API版本,因此修改对应代码,增加对hadoop 2.x API版本的的支持 代码放在https://github. ...
-
C#的深拷贝和浅拷贝
也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...
-
网站图标 favicon.ico
默认情况下,浏览器访问一个网站的时候,同时还会向服务器请求“/favicon.ico”这个URL,目的是获取网站的图标. 若没有配置的话,Django就会返回一个404错误,并且浏览器接收到这个404 ...
-
springboot实现服务器端消息推送(websocket + sockjs + stomp)
服务器端推送技术在web开发中比较常用,可能早期很多人的解决方案是采用ajax向服务器轮询消息,这种方式的轮询频率不好控制,所以大大增加了服务器的压力,后来有了下面的方案:当客户端向服务器发送请求时, ...