diff --git a/pom.xml b/pom.xml index b0e8867..cba8351 100644 --- a/pom.xml +++ b/pom.xml @@ -101,5 +101,13 @@ hutool-all 5.0.2 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + diff --git a/src/main/java/pres/auxiliary/work/selenium/brower/AbstractBrower.java b/src/main/java/pres/auxiliary/work/selenium/brower/AbstractBrower.java index 2dc1de3..84d7e2d 100644 --- a/src/main/java/pres/auxiliary/work/selenium/brower/AbstractBrower.java +++ b/src/main/java/pres/auxiliary/work/selenium/brower/AbstractBrower.java @@ -1,7 +1,9 @@ package pres.auxiliary.work.selenium.brower; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Set; import org.openqa.selenium.JavascriptExecutor; @@ -33,7 +35,7 @@ public abstract class AbstractBrower { /** * 存储打开的页面 */ - HashMap pageList = new HashMap(16); + HashMap pageMap = new HashMap(16); /** * 用于存储WebDriver当前指向的页面信息 @@ -135,9 +137,9 @@ public abstract class AbstractBrower { // 若pageList无元素,则表明此为第一次打开浏览器,则无论openNewLabel是何值,均按照同一规则打开页面 // 若pageList有元素,则根据openNewLabel参数来决定如何打开新的页面 - if (pageList.size() == 0) { + if (pageMap.size() == 0) { // 存储页面对象 - pageList.put(newPage.getPageName(), newPage); + pageMap.put(newPage.getPageName(), newPage); // 将当前页面对象指向newPage nowPage = newPage; // 在当前标签上打开页面 @@ -145,15 +147,15 @@ public abstract class AbstractBrower { } else { if (openNewLabel) { // 存储页面对象 - pageList.put(newPage.getPageName(), newPage); + pageMap.put(newPage.getPageName(), newPage); // 将当前页面对象指向newPage nowPage = newPage; // 在标签页上打开页面 openNewLabelPage(); } else { // 先在pageList移除nowPage - pageList.remove(nowPage.getPageName()); - pageList.put(newPage.getPageName(), newPage); + pageMap.remove(nowPage.getPageName()); + pageMap.put(newPage.getPageName(), newPage); // 将nowPage指向newPage nowPage = newPage; // 在当前标签上打开页面 @@ -193,7 +195,7 @@ public abstract class AbstractBrower { public JSONObject getAllInformation() { // 遍历所有标签页,存储标签页信息 JSONArray labelInformation = new JSONArray(); - pageList.forEach((name, page) -> { + pageMap.forEach((name, page) -> { labelInformation.add(page.getPageInformation()); }); // 存储标签页信息 @@ -203,28 +205,20 @@ public abstract class AbstractBrower { } /** - * 用于根据名称返回对浏览器的各项信息,若信息不存在,则返回空 - * - * @param key 需要搜索的信息名称 - * @return 名称对应的浏览器信息 + * 用于返回当前在浏览器中被打开的页面 + * @return 在浏览器中被打开的{@link Page}对象 */ - public String getInformation(String key) { - if (informationJson.containsKey(key)) { - //若需要查看标签信息,则对标签信息即时进行存储 - if ("标签信息".equals(key)) { - // 遍历所有标签页,存储标签页信息 - JSONArray labelInformation = new JSONArray(); - pageList.forEach((name, page) -> { - labelInformation.add(page.getPageInformation()); - }); - // 存储标签页信息 - informationJson.put("标签信息", labelInformation); + public List getOpenPage() { + List pageList = new ArrayList<>(); + + //遍历pageMap,存储所有存在handle的Page对象 + pageMap.forEach((k, v) -> { + if (!v.getHandle().isEmpty()) { + pageList.add(v); } - - return informationJson.getString(key); - } else { - return ""; - } + }); + + return pageList; } /** @@ -261,14 +255,14 @@ public abstract class AbstractBrower { driver.switchTo().window(newHandle); // 将标签内容全部置空及当前页面内容置空 - pageList.clear(); + pageMap.clear(); nowPage = null; } else { // 根据当前窗口handle查找相应的page对象 Page page = findPage(driver.getWindowHandle()); // 若窗口指向的页面存在,则将该页面从类中移除 if (page != null) { - pageList.remove(page.getPageName()); + pageMap.remove(page.getPageName()); } // 关闭当前标签 @@ -290,7 +284,7 @@ public abstract class AbstractBrower { //将driver指定为null driver = null; // 清空页面存储的内容 - pageList.clear(); + pageMap.clear(); nowPage = null; } @@ -314,7 +308,7 @@ public abstract class AbstractBrower { */ public void switchWindow(Page page) { // 查找pageList中是否存在传入的page,若存在,则获取相应的handle后对窗口进行切换 - if (pageList.containsKey(page.getPageName())) { + if (pageMap.containsKey(page.getPageName())) { try { driver.switchTo().window(page.getHandle()); } catch (NoSuchWindowException e) { @@ -404,8 +398,8 @@ public abstract class AbstractBrower { * @return 页面对应窗口的Handle */ private String findPageHandle(String pageName) { - if (pageList.containsKey(pageName)) { - return pageList.get(pageName).getHandle(); + if (pageMap.containsKey(pageName)) { + return pageMap.get(pageName).getHandle(); } else { return ""; } @@ -419,10 +413,10 @@ public abstract class AbstractBrower { */ private Page findPage(String handle) { // 遍历所有的page,查询与传入相同的handle - for (String pageName : pageList.keySet()) { + for (String pageName : pageMap.keySet()) { // 若存储的handle与传入的handle相同,则对其进行 - if (handle.equals(pageList.get(pageName).getHandle())) { - return pageList.get(pageName); + if (handle.equals(pageMap.get(pageName).getHandle())) { + return pageMap.get(pageName); } } diff --git a/src/main/java/pres/auxiliary/work/selenium/element/AbstractElement.java b/src/main/java/pres/auxiliary/work/selenium/element/AbstractElement.java index b5bb99e..de72a42 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/AbstractElement.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/AbstractElement.java @@ -6,18 +6,20 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import pres.auxiliary.selenium.event.NoSuchWindownException; import pres.auxiliary.selenium.xml.ByType; import pres.auxiliary.selenium.xml.ReadXml; +import pres.auxiliary.work.selenium.brower.AbstractBrower; +import pres.auxiliary.work.selenium.brower.Page; /** *

文件名:AbstractElement.java

@@ -40,7 +42,12 @@ public abstract class AbstractElement { /** * 用于指向存储控件定位方式的xml文件 */ - ReadXml xml = new ReadXml(); + ReadXml xml; + + /** + * 用于存储浏览器对象 + */ + AbstractBrower brower; /** * 存储单个控件的等待时间 */ @@ -55,7 +62,7 @@ public abstract class AbstractElement { private ArrayList iframeNameList = new ArrayList<>(); /** - * 用于存储元素通用的等待时间 + * 用于存储元素通用的等待时间,默认5秒 */ private long waitTime = 5; @@ -65,15 +72,24 @@ public abstract class AbstractElement { boolean isAutoSwitchIframe = true; /** - * 构造对象并存储浏览器的WebDriver对象 + * 通过{@link WebDriver}对象进行构造 * - * @param driver 浏览器的WebDriver对象 + * @param driver {@link WebDriver}对象 */ public AbstractElement(WebDriver driver) { this.driver = driver; browserHandles = this.driver.getWindowHandle(); } + /** + * 通过浏览器对象{@link AbstractBrower}进行构造 + * @param brower {@link AbstractBrower}对象 + */ + public AbstractElement(AbstractBrower brower) { + this.brower = brower; + this.driver = brower.getDriver(); + } + /** * 用于对单个控件设置等待时间 * @@ -115,7 +131,11 @@ public abstract class AbstractElement { * @param isBreakRootFrame 是否需要将窗体切回到顶层 */ public void setXmlFile(File xmlFile, boolean isBreakRootFrame) { - xml.setXmlPath(xmlFile); + if (xml == null) { + xml = new ReadXml(xmlFile); + } else { + xml.setXmlPath(xmlFile); + } if (isBreakRootFrame) { switchRootFrame(); @@ -199,16 +219,24 @@ public abstract class AbstractElement { * @see #switchFrame(String) */ public void switchFrame(String name, ByType byType) { - List nameList = new ArrayList(); + List nameList = new ArrayList(); //判断传入的元素名称是否存在于xml文件中,若存在,则将该元素的父层名称存储至nameList if (xml != null && xml.isElement(name) && isAutoSwitchIframe) { nameList.addAll(getParentFrameName(name)); } - //将相应的元素存入nameList中 - nameList.add(new ElementInformation(name, byType, controlWaitTime.containsKey(name) ? controlWaitTime.get(name) : waitTime)); - //调用 + //调用切换窗体的方法 switchFrame(nameList); + + //将相应的元素存入nameList中 + if (byType != null) { + driver.switchTo().frame(recognitionElements(new ElementInformation(name, byType, getWaitTime(name))).get(0)); + } else { + driver.switchTo().frame(recognitionElements(new ElementInformation(name, getWaitTime(name))).get(0)); + } + //切换窗体 + + iframeNameList.add(name); } /** @@ -230,12 +258,12 @@ public abstract class AbstractElement { * * @param elementInformationList 存储窗体的名称或xpath与css定位方式的List集合 */ - private void switchFrame(List elementInformationList) { - elementInformationList.forEach(elementInformation -> { + void switchFrame(List frameNameList) { + frameNameList.forEach(frameName -> { //判断name指向的窗体是否在iframeNameList中,若存在,则向上切换父层,直到切换到name指向的窗体;若不存在,则直接切换,并添加窗体名称 - if (iframeNameList.contains(elementInformation.name)) { + if (iframeNameList.contains(frameName)) { //获取name窗体在iframeNameList中的位置 - int index = iframeNameList.indexOf(elementInformation.name); + int index = iframeNameList.indexOf(frameName); //获取需要向上切换窗体的次数,公式为推断出来 int count = iframeNameList.size() - index - 1; for (int i = 0; i < count; i++) { @@ -243,36 +271,12 @@ public abstract class AbstractElement { } } else { //切换窗体 - driver.switchTo().frame(recognitionElements(elementInformation).get(0)); - iframeNameList.add(elementInformation.name); + driver.switchTo().frame(recognitionElements(new ElementInformation(frameName, getWaitTime(frameName))).get(0)); + iframeNameList.add(frameName); } }); } - /** - * 该方法可用于切换弹出的窗口(新标签或新窗口),并返回新窗口的WebDriver对象,若无新窗口,则返回当前的窗口的WebDriver对象。 - * 注意,该方法只能切换弹出一个窗口的情况,若有多个窗口,通过该方法无法准确定位,可参考方法{@link #switchWindow(String)}。 - */ - public void switchWindow() { - Set handles = driver.getWindowHandles(); - // 判断是否只存在一个窗体,若只存在一个,则直接返回当前浏览器的WebDriver对象 - if (handles.size() == 1) { - return; - } - - // 获取当前窗口的handle - String winHandle = driver.getWindowHandle(); - // 循环,获取所有的页面handle - for (String newWinHandle : handles) { - // 判断获取到的窗体handle是否为当前窗口的handle,若不是,则将其定位到获取的handle对应的窗体上 - if (!newWinHandle.equals(winHandle)) { - driver.switchTo().window(newWinHandle); - } - } - - throw new NoSuchWindownException("未找到相应的窗体"); - } - /** * 该方法用于将窗口切换回最原始的窗口上。 */ @@ -294,18 +298,46 @@ public abstract class AbstractElement { if (handles.size() == 1) { return; } + + List pageList = new ArrayList<>(); + //若浏览器对象存在,则将已打开的页面的handle进行存储,优先遍历新打开的标签 + if (brower != null) { + pageList.addAll(brower.getOpenPage()); + } + + //移除已打开的窗口 + handles.removeAll(pageList.stream().map(page -> { + return page.getHandle(); + }).collect(Collectors.toList())); // 循环,获取所有的页面handle for (String newWinHandle : handles) { + //切换窗口,并查找元素是否在窗口上,若存在,则结束切换 driver.switchTo().window(newWinHandle); - // 调用judgeElementMode()方法来判断元素是否存在,如果元素存在,则返回相应页面的WebDriver对象,若抛出异常(元素不存在),则返回当前 try { - recognitionElements(controlName).get(0); - } catch (TimeoutException e) { + //构造信息,因为在构造过程中会判断元素是否存在, + new ElementInformation(controlName, getWaitTime(controlName)); + return; + }catch (Exception e) { continue; } } - + + //若不在新打开的窗口上,则遍历已打开的窗口 + if (brower != null) { + for (Page page : pageList) { + //切换窗口,并查找元素是否在窗口上,若存在,则结束切换 + brower.switchWindow(page); + try { + new ElementInformation(controlName, getWaitTime(controlName)); + return; + }catch (Exception e) { + continue; + } + } + } + + //若遍历所有窗口后均未能查到元素,则抛出异常 throw new NoSuchWindownException("未找到存在元素" + controlName + "所在的窗体"); } @@ -375,118 +407,20 @@ public abstract class AbstractElement { * @throws UnrecognizableLocationModeException 元素无法识别时抛出的异常 */ List recognitionElements(ElementInformation element) { - //判断元素是否存在于xml文件中,根据返回的状态,来判断调用的方法 - if (xml.isElement(element.name)) { - return findXmlElement(element); - } else { - return findCommonElement(element); - } - } - - /** - * 根据传入的元素定位方式,返回在页面上查找到的WebElement对象 - * @param name 元素内容 - * @return - */ - private List findCommonElement(ElementInformation element) { - //若未对元素的定位方式进行存储,则调用方法,对元素的定位方式进行识别 - if (element.byType == null) { - element.byType = judgeElementLocationMode(element.value); - } - - if (isExistElement(element)) { - return driver.findElements(getBy(element.byType, element.value)); - } - - // 若循环结束后仍未能找到该元素,则返回一个空串 - throw new TimeoutException("元素“" + element.name + "”无法查找,请核对定位方式:" + element.byType.getValue() + "=" + element.value); - } - - /** - * 根据传入的元素名称,到指定的xml文件中查找相应的有效的定位方式,并在页面中查找,返回查找到的元素对象 - * @param name 需要查找的元素名称 - * @return 页面中查找到的元素 - * @throws TimeoutException 当元素不能找到时抛出的异常 - */ - private List findXmlElement(ElementInformation element) { - //若元素的定位方式未被存储,则调用方法对元素的定位方式进行获取 - if (element.byType == null || element.value.isEmpty()) { - // 循环,逐个在页面上配对有效的标签对应的定位方式 - for (ByType mode : xml.getElementMode(element.name)) { - //存储当前查询到的元素信息 - element.byType = mode; - element.value = xml.getValue(element.name, mode); - //若元素能被找到,则结束循环 - if (isExistElement(element)) { - break; - } - } - - // 若循环结束后仍未能找到该元素,则抛出异常 - throw new TimeoutException("元素“" + element.name + "”无法查找,请核对xml文件:" + xml.getXmlFile().getName() + "\n文件路径:" + xml.getXmlFile().getAbsolutePath()); - } - - return driver.findElements(getBy(element.byType, element.value)); + return driver.findElements(element.getBy()); } /** - * 用于判断传入参数的定位方式,只识别xpath路径与绝对的css路径两种定位方式。 - * - * @param text 元素定位方式 - * @return {@link ByType}枚举 + * 用于返回控件的等待时间,若设置单个控件的等待时间(使用{@link #setContorlWaitTime(String, long)}方法设置), + * 则返回设置的控件等待时间;若未设置单个控件的等待时间,则返回设置的通用等待时间(使用{@link #setWaitTime(long)}方法) + * ;若未对通用时间进行设置,则返回默认时间({@link #waitTime}) + * @param name 控件名称 + * @return 相应控件的等待时间 + * @see #setContorlWaitTime(String, long) + * @see #setWaitTime(long) */ - private ByType judgeElementLocationMode(String text) { - // 如果抛出元素名称查找不到的的异常,则对应匹配xpath和绝对css路径两种定位方式 - // 匹配xpath定位,判定方法,判断text的第一个字符是否是“/” - if (text.indexOf("/") == 0) { - // 查找该定位方式在有限的时间内是否内被查到 - return ByType.XPATH; - } else if (text.indexOf("html") == 0) { - return ByType.CSS; - } else { - throw new UnrecognizableLocationModeException("元素定位方式类型无法识别:" + text); - } - } - - /** - * 根据页面的等待时间和元素定位方式,在页面上查找相应的元素,返回是否能查到元素 - * @param time 控件等待时间 - * @param by 元素定位方式 - * @return 是否能查找到的元素 - */ - boolean isExistElement(ElementInformation element) { -// new WebDriverWait(driver, time, 200).until(ExpectedConditions.elementToBeClickable(by)); - By by = getBy(element.byType, element.value); - - //当查找到元素时,则返回true,若查不到元素,则会抛出异常,故返回false - try { - new WebDriverWait(driver, element.waitTime, 200).until(ExpectedConditions.presenceOfElementLocated(by)); - return true; - } catch (Exception e) { - return false; - } - } - - By getBy(ByType byType, String value) { - //根据元素的定位方式,对定位内容进行选择,返回相应的By对象 - switch (byType) { - case XPATH: - return By.xpath(value); - case CLASSNAME: - return By.className(value); - case CSS: - return By.cssSelector(value); - case ID: - return By.id(value); - case LINKTEXT: - return By.linkText(value); - case NAME: - return By.name(value); - case TAGNAME: - return By.tagName(value); - default: - throw new UnrecognizableLocationModeException("无法识别的定位类型:" + byType); - } + long getWaitTime(String name) { + return controlWaitTime.containsKey(name) ? controlWaitTime.get(name) : waitTime; } /** @@ -495,16 +429,16 @@ public abstract class AbstractElement { * @param name 元素在xml文件中的名称 * @return 元素在xml文件中所有的父窗体集合 */ - List getParentFrameName(String name) { + List getParentFrameName(String name) { //存储获取到的父层窗体名称 - List nameList = new ArrayList(); + List nameList = new ArrayList(); //获取元素所在窗体的名称 String iframeName = xml.getIframeName(name); //循环,判断窗体是否存在(方法返回不为空),若存在,则再将父窗体进行存储 while(!iframeName.isEmpty()) { //存储窗体 - nameList.add(new ElementInformation(iframeName, controlWaitTime.containsKey(iframeName) ? controlWaitTime.get(iframeName) : waitTime)); + nameList.add(iframeName); //再以当前窗体的名称再次获取该窗体的父窗体 iframeName = xml.getIframeName(iframeName); } @@ -570,9 +504,13 @@ public abstract class AbstractElement { this.name = name; this.waitTime = waitTime; - //若未指定xml文件或xml文件中不存在name对应的元素,则将name的值赋给value,表示 + //若未指定xml文件,或者在xml文件中无法查到相应的元素时,则将name的值赋给value,且根据value判断相应定位方式 if (xml == null || !xml.isElement(name)) { value = name; + setCommonElementLocationMode(); + } else { + //若指定了xml文件,且传入的元素名称存在与xml文件中,则判断元素相应的定位方式及定位内容 + setXmlElementLocation(); } } @@ -589,12 +527,13 @@ public abstract class AbstractElement { //若未指定xml文件,则将name的值赋给value if (xml == null) { value = name; - } - //xml文件中不存在name对应的元素,则将name的值赋给value;反之,则在xml文件中查找对应的定位内容 - if (!xml.isElement(name)) { - value = name; } else { - value = xml.getValue(name, byType); + //xml文件中不存在name对应的元素,则将name的值赋给value;反之,则在xml文件中查找对应的定位内容 + if (!xml.isElement(name)) { + value = name; + } else { + value = xml.getValue(name, byType); + } } } @@ -621,5 +560,109 @@ public abstract class AbstractElement { public String getValue() { return value; } + + /** + * 用于根据传入的参数,识别非xml文件内的元素定位方式。 + * 该方法能快速识别xpath定位方式以及绝对css定位方式,若不是以上两种定位方式 + * 则会遍历所有的定位方式,此时会降低运行速度,建议在不是以上两种定位方式的 + * 情况下,直接指定元素的定位方式,以提高效率 + */ + void setCommonElementLocationMode() { + // 如果抛出元素名称查找不到的的异常,则对应匹配xpath和绝对css路径两种定位方式 + // 匹配xpath定位,判定方法,判断text的第一个字符是否是“/” + if (value.indexOf("/") == 0) { + // 查找该定位方式在有限的时间内是否内被查到 + byType = ByType.XPATH; + //在页面中查找元素,若元素能找到,则结束查找 + if (isExistElement()) { + return; + } + } else if (value.indexOf("html") == 0) { + byType = ByType.CSS; + //在页面中查找元素,若元素能找到,则结束查找 + if (isExistElement()) { + return; + } + } else { + //若元素无法识别,则将所有的定位类型(排除xpath类型)与之进行对比,直到在页面上找到元素为止 + for(ByType type : ByType.values()) { + if (type == ByType.XPATH) { + continue; + } + + byType = type; + //在页面中查找元素,若元素能找到,则结束查找 + if (isExistElement()) { + return; + } + } + } + + //若所有的定位方式均无法查找到元素,则抛出异常 + throw new UnrecognizableLocationModeException("元素定位方式类型无法识别:" + value); + } + + /** + * 用于设置xml文件内的元素的定位方式及定位内容 + */ + void setXmlElementLocation() { + // 循环,逐个在页面上配对有效的标签对应的定位方式 + for (ByType mode : xml.getElementMode(name)) { + //存储当前查询到的元素信息 + byType = mode; + value = xml.getValue(name, mode); + + //若元素能被找到,则结束循环 + if (isExistElement()) { + break; + } + + // 若循环结束后仍未能找到该元素,则抛出异常 + throw new TimeoutException("元素“" + name + "”无法查找,请核对xml文件:" + xml.getXmlFile().getName() + "\n文件路径:" + xml.getXmlFile().getAbsolutePath()); + } + } + + /** + * 根据元素的参数,返回元素的By对象 + * @return 元素的By对象 + */ + By getBy() { + //根据元素的定位方式,对定位内容进行选择,返回相应的By对象 + switch (byType) { + case XPATH: + return By.xpath(value); + case CLASSNAME: + return By.className(value); + case CSS: + return By.cssSelector(value); + case ID: + return By.id(value); + case LINKTEXT: + return By.linkText(value); + case NAME: + return By.name(value); + case TAGNAME: + return By.tagName(value); + default: + throw new UnrecognizableLocationModeException("无法识别的定位类型:" + byType); + } + } + + /** + * 根据页面的等待时间和元素定位方式,在页面上查找相应的元素,返回是否能查到元素 + * @param time 控件等待时间 + * @param by 元素定位方式 + * @return 是否能查找到的元素 + */ + boolean isExistElement() { +// new WebDriverWait(driver, time, 200).until(ExpectedConditions.elementToBeClickable(by)); +// new WebDriverWait(driver, time, 200).until(ExpectedConditions.titleContains("")); + //当查找到元素时,则返回true,若查不到元素,则会抛出异常,故返回false + return new WebDriverWait(driver, waitTime, 200). + until((driver) -> { + WebElement element = driver.findElement(getBy()); + return element != null; + }); + } } } diff --git a/src/main/java/pres/auxiliary/work/selenium/element/CommonElement.java b/src/main/java/pres/auxiliary/work/selenium/element/CommonElement.java index 20196b1..1cc22f4 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/CommonElement.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/CommonElement.java @@ -3,6 +3,23 @@ package pres.auxiliary.work.selenium.element; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import pres.auxiliary.selenium.xml.ByType; +import pres.auxiliary.work.selenium.brower.AbstractBrower; + +/** + *

文件名:CommonElement.java

+ *

用途: + * 提供在辅助化测试中,对页面单一元素获取的方法。类中获取元素的方法兼容传入定位方式对 + * 元素进行查找,建议使用xml对页面元素的定位方式进行存储,以简化编码时的代码量,也便于 + * 对代码的维护 + *

+ *

编码时间:2020年4月26日下午10:34:55

+ *

修改时间:2020年4月26日下午10:34:55

+ * @author + * @version Ver1.0 + * @since JDK 12 + * + */ public class CommonElement extends AbstractElement { /** * 构造对象并存储浏览器的WebDriver对象 @@ -13,22 +30,43 @@ public class CommonElement extends AbstractElement { super(driver); } + /** + * 通过浏览器对象{@link AbstractBrower}进行构造 + * @param brower {@link AbstractBrower}对象 + */ + public CommonElement(AbstractBrower brower) { + super(brower); + } + /** * 用于根据xml文件中元素的名称,返回对应的WebElement对象。该方法亦可传入元素 - * 的xpath或css定位内容,来获取元素的WebElement对象。 + * 定位内容,通过遍历所有的定位方式,在页面上查找元素,来获取元素的WebElement对象。 + * 建议传入的定位内容为xpath路径或绝对的css路径,若非这两路径,则在识别元素时会很慢,降低 + * 程序运行速度。若非xml文件中的元素,且不是xpath路径或绝对的css路径,建议使用{@link #getWebElement(String, ByType)}方法 * @param name 元素的名称或元素定位内容 * @return WebElement对象 */ public WebElement getWebElement(String name) { //判断传入的元素是否在xml文件中,若存在再判断是否自动切换窗体,若需要,则获取元素的所有父窗体并进行切换 - if (xml.isElement(name)) { - //判断元素是否需要自动切换窗体 - if (isAutoSwitchIframe) { - switchFrame(getParentFrameName(name)); - } + if (xml != null && xml.isElement(name) && isAutoSwitchIframe) { + switchFrame(getParentFrameName(name)); } - return null; + return recognitionElements(new ElementInformation(name, getWaitTime(name))).get(0); + } + + /** + * 用于根据xml文件中元素的名称,与定位方式,返回对应的WebElement对象。该方法亦可传入元素 + * 定位内容,并根据定位方式,对页面数据进行查找 + * @param name 元素的名称或元素定位内容 + * @return WebElement对象 + */ + public WebElement getWebElement(String name, ByType byType) { + //判断传入的元素是否在xml文件中,若存在再判断是否自动切换窗体,若需要,则获取元素的所有父窗体并进行切换 + if (xml != null && xml.isElement(name) && isAutoSwitchIframe) { + switchFrame(getParentFrameName(name)); + } + + return recognitionElements(new ElementInformation(name, byType, getWaitTime(name))).get(0); } - } diff --git a/src/main/java/pres/auxiliary/work/selenium/element/DataListElement.java b/src/main/java/pres/auxiliary/work/selenium/element/DataListElement.java new file mode 100644 index 0000000..d62c45b --- /dev/null +++ b/src/main/java/pres/auxiliary/work/selenium/element/DataListElement.java @@ -0,0 +1,80 @@ +package pres.auxiliary.work.selenium.element; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.WebDriverWait; + +import pres.auxiliary.work.selenium.brower.AbstractBrower; + +/** + *

文件名:DataListElement.java

+ *

用途: + * 提供在辅助化测试中,对页面列表元素获取的方法,并对列表元素的获取做了优化。 + * 类中获取元素的方法兼容传入定位方式对元素进行查找,建议使用xml对页面元素的 + * 定位方式进行存储,以简化编码时的代码量,也便于对代码的维护。 + *

+ *

编码时间:2020年4月29日下午6:18:46

+ *

修改时间:2020年4月29日下午6:18:46

+ * @author 彭宇琦 + * @version Ver1.0 + * @since JDK 12 + * + */ +public class DataListElement extends AbstractElement { + /** + * 用于存储获取到的列表一列元素,key为列表名称,value为列表元素 + */ + private HashMap> elementMap = new HashMap<>(16); + + /** + * 用于判断列表的第一行元素是否为标题元素 + */ + private boolean isFristRowTitle = false; + + /** + * 通过浏览器对象{@link AbstractBrower}进行构造 + * @param brower {@link AbstractBrower}对象 + */ + public DataListElement(AbstractBrower brower) { + super(brower); + } + + /** + * 构造对象并存储浏览器的WebDriver对象 + * + * @param driver 浏览器的WebDriver对象 + */ + public DataListElement(WebDriver driver) { + super(driver); + } + + /** + * 用于设置首行元素是否为标题元素 + * @param isFristRowTitle 首行是否为标题元素 + */ + public void setFristRowTitle(boolean isFristRowTitle) { + this.isFristRowTitle = isFristRowTitle; + } + + /** + * 用于根据xml文件中元素的名称,返回对应的获取到的一组WebElement对象。该方法亦可传入元素 + * 定位内容,通过遍历所有的定位方式,在页面上查找元素,来获取元素的WebElement对象。 + * 建议传入的定位内容为xpath路径或绝对的css路径,若非这两路径,则在识别元素时会很慢,降低 + * 程序运行速度。 + * + * @param names 一组控件的名称或xpath与css定位方式 + */ + public void add(String name) { + //判断当前列名是否存在,不存在,则先存储其类名 + if (!elementMap.containsKey(name)) { + elementMap.put(name, new ArrayList()); + } + + + } +} diff --git a/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java b/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java new file mode 100644 index 0000000..d4feb7f --- /dev/null +++ b/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java @@ -0,0 +1,28 @@ +package pres.auxiliary.work.selenium.element; + +public class NoSuchWindownException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public NoSuchWindownException() { + super(); + } + + public NoSuchWindownException(String arg0, Throwable arg1, boolean arg2, boolean arg3) { + super(arg0, arg1, arg2, arg3); + } + + public NoSuchWindownException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public NoSuchWindownException(String arg0) { + super(arg0); + } + + public NoSuchWindownException(Throwable arg0) { + super(arg0); + } + + +} diff --git a/src/main/java/pres/auxiliary/work/testcase/file/AbstractTestCaseWrite.java b/src/main/java/pres/auxiliary/work/testcase/file/AbstractTestCaseWrite.java index 34a7d9a..1c00221 100644 --- a/src/main/java/pres/auxiliary/work/testcase/file/AbstractTestCaseWrite.java +++ b/src/main/java/pres/auxiliary/work/testcase/file/AbstractTestCaseWrite.java @@ -357,7 +357,7 @@ public abstract class AbstractTestCaseWrite> } /** - * 用于将生成测试用例方法(继承自{@link Case}类的方法)所成成的测试用例添加到测试用例文件中 + * 用于将测试用例模板(继承自{@link Case}类的方法)所成的测试用例添加到测试用例文件中 * * @param testCase 测试用例生成方法 * @return 类本身 diff --git a/src/main/java/pres/auxiliary/work/testcase/file/JiraTestCaseWrite.java b/src/main/java/pres/auxiliary/work/testcase/file/JiraTestCaseWrite.java index 42f72d1..c8e824a 100644 --- a/src/main/java/pres/auxiliary/work/testcase/file/JiraTestCaseWrite.java +++ b/src/main/java/pres/auxiliary/work/testcase/file/JiraTestCaseWrite.java @@ -67,7 +67,7 @@ public class JiraTestCaseWrite extends CommonTestCaseWrite { * @since JDK 12 * */ - enum JiraFieldIdType { + public enum JiraFieldIdType { /** * 标题(Name) */ diff --git a/src/test/java/pres/auxiliary/work/selenium/element/CommonElementTest.java b/src/test/java/pres/auxiliary/work/selenium/element/CommonElementTest.java new file mode 100644 index 0000000..7a9ca43 --- /dev/null +++ b/src/test/java/pres/auxiliary/work/selenium/element/CommonElementTest.java @@ -0,0 +1,79 @@ +package pres.auxiliary.work.selenium.element; + +import java.io.File; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import pres.auxiliary.work.selenium.brower.ChromeBrower; +import pres.auxiliary.work.selenium.brower.ChromeBrower.ChromeOptionType; + +/** + *

文件名:CommonElementTest.java

+ *

用途: + * 对{@link CommonElement}类方法进行单元测试 + *

+ *

测试对象:桂建通工资管理的工资单管理模块,获取第一条数据的单位信息

+ *

编码时间:2020年4月30日上午7:44:34

+ *

修改时间:2020年4月30日上午7:44:34

+ * @author + * @version Ver1.0 + * @since JDK 12 + * + */ +public class CommonElementTest { + ChromeBrower cb = new ChromeBrower(new File("Resource/BrowersDriver/Chrom/78.0394.70/chromedriver.exe")); + CommonElement ce; + + @BeforeClass + public void initDate() { + cb.addConfig(ChromeOptionType.CONTRAL_OPEN_BROWER, "127.0.0.1:9222"); + ce = new CommonElement(cb); + } + + /** + * 用于测试非xml文件中的传参进行窗体切换与元素的获取 + */ + @Test + public void getCommonElementTest() { + ce.switchFrame("//iframe[contains(@src, '/Regulatory/admin/index.jsp')]"); + ce.switchFrame("//iframe[contains(@src, '工资单管理')]"); + System.out.println(ce.getWebElement("//*[@id=\"listBox\"]/li[1]/div[1]/p/span[1]").getText()); + } + + /** + * 用于测试xml文件中的传参进行窗体切换与元素的获取 + */ + @Test + public void getXmlElementTest() { + File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml"); + ce.setXmlFile(xmlFile, false); + ce.setAutoSwitchIframe(false); + ce.switchFrame("主窗体"); + ce.switchFrame("工资发放详情"); + System.out.println(ce.getWebElement("单位名称").getText()); + } + + /** + * 用于测试xml文件的自动定位窗体 + */ + @Test + public void autoLocationElementTest() { + File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml"); + ce.setXmlFile(xmlFile, false); + System.out.println(ce.getWebElement("单位名称").getText()); + } + + /** + * 用于测试xml文件的多次切换窗体后自动定位窗体 + */ + @Test + public void exceptAutoLocationElementTest() { + File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml"); + ce.setXmlFile(xmlFile, false); + //先切主窗体 + ce.switchFrame("主窗体"); + //在获取元素前,会判断元素所在窗体,由于主窗体是爷爷辈窗体,获取元素前会切换工资发放详情窗体 + System.out.println(ce.getWebElement("单位名称").getText()); + } +} diff --git a/src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml b/src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml new file mode 100644 index 0000000..2be9a7f --- /dev/null +++ b/src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml @@ -0,0 +1,21 @@ + + + + + //iframe[contains(@src,'${src}')] + + + + + \ No newline at end of file