();
//获取元素所在窗体的名称
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