之前已经写过一篇:
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
时间: 2024-12-15 01:49:10