添加外链xml功能

This commit is contained in:
彭宇琦 2020-07-02 08:40:33 +08:00
parent d56a49de5d
commit a9ba0eb7c1
7 changed files with 188 additions and 53 deletions

View File

@ -2,6 +2,7 @@ package pres.auxiliary.work.selenium.element;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -462,9 +463,9 @@ public abstract class AbstractBy {
private By recognitionXmlElement(ElementInformation elementInformation) {
//判断传入的ByType对象是否为null
if (elementInformation.byType == null) {
return judgeXmlElementBy(elementInformation.name);
return judgeXmlElementBy(elementInformation.name, elementInformation.linkKeyList);
} else {
By by = xml.getBy(elementInformation.name, elementInformation.byType);
By by = xml.getBy(elementInformation.name, elementInformation.byType, elementInformation.linkKeyList);
if (isExistElement(by, getWaitTime(elementInformation.name)))
return by;
else
@ -556,11 +557,11 @@ public abstract class AbstractBy {
/**
* 用于设置xml文件内的元素的定位方式及定位内容
*/
By judgeXmlElementBy(String name) {
By judgeXmlElementBy(String name, List<String> linkList) {
By by;
// 循环逐个在页面上配对有效的标签对应的定位方式
for (ByType mode : xml.getElementMode(name)) {
by = getBy(xml.getValue(name, mode), mode);
by = getBy(xml.getValue(name, mode, linkList), mode);
//若元素能被找到则返回相应的By对象若未找到则再次循环
if (isExistElement(by, getWaitTime(name))) {
@ -626,7 +627,7 @@ public abstract class AbstractBy {
* <p><b>修改时间</b>2020年5月22日上午8:18:39</p>
* @author 彭宇琦
* @version Ver1.1
* @since JDK 12
* @since JDK 1.8
*
*/
class ElementInformation {
@ -642,6 +643,10 @@ public abstract class AbstractBy {
* 用于标记元素的类型
*/
public ElementType elementType;
/**
*
*/
public ArrayList<String> linkKeyList = new ArrayList<>();
/**
* 初始化信息
* @param name 元素名称或定位内容
@ -663,6 +668,20 @@ public abstract class AbstractBy {
this.byType = byType;
}
/**
* 初始化信息
* @param name 元素名称或定位内容
* @param byType 元素定位
* @param elementType 元素类型
* @param links 元素外链信息
*/
public ElementInformation(String name, ByType byType, ElementType elementType, String...links) {
this.name = name;
this.byType = byType;
linkKeyList.addAll(Arrays.asList(links));
}
@Override
public boolean equals(Object obj) {
if (this == obj)

View File

@ -44,12 +44,12 @@ public class CommonBy extends AbstractBy {
* 用于根据xml文件中元素的名称返回对应的{@link Element}对象该方法亦可传入元素
* 定位内容通过遍历所有的定位方式在页面上查找元素来获取元素的WebElement对象
* 建议传入的定位内容为xpath路径或绝对的css路径若非这两路径则在识别元素时会很慢降低
* 程序运行速度若非xml文件中的元素且不是xpath路径或绝对的css路径建议使用{@link #getWebElement(String, ByType)}方法
* 程序运行速度若非xml文件中的元素且不是xpath路径或绝对的css路径建议使用{@link #getElement(String, ByType)}方法
* @param name 元素的名称或元素定位内容
* @return {@link Element}对象
*/
public Element getElement(String name) {
return getElement(name, null);
return getElement(new ElementInformation(name, null, ElementType.COMMON_ELEMENT));
}
/**
@ -61,23 +61,33 @@ public class CommonBy extends AbstractBy {
public Element getElement(String name, ByType byType) {
return getElement(new ElementInformation(name, byType, ElementType.COMMON_ELEMENT));
}
/**
* 获取元素的底层方法
* @param elementInformation 元素信息类对象
* @return WebElement对象
*/
/*
private WebElement getWebElement(ElementInformation elementInformation) {
//判断传入的元素是否在xml文件中若存在再判断是否自动切换窗体若需要则获取元素的所有父窗体并进行切换
if (xml != null && xml.isElement(elementInformation.name) && isAutoSwitchIframe) {
switchFrame(getParentFrameName(elementInformation.name));
}
return driver.findElement(recognitionElement(elementInformation));
}
*/
/**
* 用于根据xml文件中元素的名称与定位方式返回对应的{@link Element}对象该方法亦可传入元素
* 定位内容并根据定位方式对页面数据进行查找该方法可对由xml文件读取的内容进行词语替换根据
* 传参中词语的顺序对需要替换的词语进行替换
* @param name 元素名称或定位方式内容
* @param byType 元素定位方式
* @param links 替换词语
* @return {@link Element}对象
*/
public Element getElement(String name, ByType byType, String...links) {
return getElement(new ElementInformation(name, byType, ElementType.COMMON_ELEMENT, links));
}
/**
* 用于根据xml文件中元素的名称返回对应的{@link Element}对象该方法亦可传入元素
* 定位内容通过遍历所有的定位方式在页面上查找元素来获取元素的WebElement对象
* 建议传入的定位内容为xpath路径或绝对的css路径若非这两路径则在识别元素时会很慢降低
* 程序运行速度若非xml文件中的元素且不是xpath路径或绝对的css路径建议使用{@link #getElement(String, ByType, String...)}方法
* @param name 元素的名称或元素定位内容
* @param links 替换词语
* @return {@link Element}对象
*/
public Element getElement(String name, String...links) {
return getElement(name, null, links);
}
/**
* 获取元素的底层方法
* @param elementInformation 元素信息类对象

View File

@ -2,8 +2,10 @@ package pres.auxiliary.work.selenium.xml;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.dom4j.Attribute;
@ -47,6 +49,10 @@ public class ReadXml {
*/
private Document dom;
/**
* 切分公式标记
*/
private final String SPLIT_START = "\\$\\{";
/**
* 定义xml文件中模板使用的替换符开始标志
*/
@ -142,8 +148,23 @@ public class ReadXml {
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
*/
public By getBy(String name, ByType mode) {
return getBy(name, mode, null);
}
/**
* 根据元素名称在指定的xml文件中查找到相应的元素返回其元素的信息{@link By}类返回
*
* @param name 元素名称
* @param mode 定位方式枚举类对象参见{@link ByType}
* @param linkKeyList 外链关键词集合
* @return 元素对应的{@link By}类对象
*
* @throws UndefinedElementException 未找到相应的模板元素时抛出的异常
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
*/
public By getBy(String name, ByType mode, List<String> linkKeyList) {
// 存储从xml文件中读取到的元素定位
String elementPos = getValue(name, mode);
String elementPos = getValue(name, mode, linkKeyList);
// 判断传入的参数是否符合使用By类的定位方式如果符合则拼接读取XML文件的xpath若不符则抛出异常
try {
@ -194,6 +215,53 @@ public class ReadXml {
}
}
/**
* 用于根据元素名称及定位方式查找其定位方式标签中的内容并根据关键词组对需要修改的关键词
* 逐个进行修改注意该方法将根据需要修改的关键词顺序进行修改与关键词名称无关
*
* @param name 元素名称
* @param mode 定位方式枚举类对象参见{@link ByType}
* @return xml文件中的相应元素的定位值
*
* @throws UndefinedElementException 未找到相应的模板元素时抛出的异常
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
*/
public String getValue(String name, ByType mode, List<String> linkKeyList) {
//获取到元素定位方式内容
StringBuilder value = new StringBuilder(getValue(name, mode));
//判断linkKeyList是否为空或null若为空或null则直接返回
if (linkKeyList == null || linkKeyList.isEmpty()) {
return value.toString();
}
//按照公式起始符号对内容进行切分遍历切分后的每一个元素
String[] texts = value.toString().split(SPLIT_START);
//用于lambda中计算替换的词语位置
AtomicInteger index = new AtomicInteger(0);
//遍历texts
Arrays.stream(texts)
//过滤不包含END_SIGN的元素
.filter(text -> text.indexOf(END_SIGN) > -1)
//提取元素的有效替换词语${XXX}
.map(text -> START_SIGN + text.substring(0, text.indexOf(END_SIGN) + 1))
//对词语进行替换
.forEach(text -> {
//判断当前下标是否超出linkKeyList最大元素个数若超出则结束当前执行
if (index.get() >= linkKeyList.size()) {
return;
}
//获取该字段在value中第一次出现的位置
int signIndex = value.indexOf(text);
// 将所有与该标志替换为元素属性中存储的内容使用拼接的方式进行替换
value.replace(signIndex, signIndex + text.length(), linkKeyList.get(index.getAndAdd(1)));
});
return value.toString();
}
/**
* 返回元素的所在的窗体
* @param name 元素在xml文件中的名称
@ -253,7 +321,7 @@ public class ReadXml {
"//templet/" + mode.getValue() + "[@id='" + element.attribute("temp_id").getValue() + "']");
// 如果templetElement元素为null无法查找到则抛出UndefinedElementException
if (templetElement == null) {
throw new UndefinedElementException("未定义的模板元素定位方式为:" + mode.getValue() + "模板id为"
throw new UndefinedElementException("未定义的模板元素定位方式为:" + mode.getValue() + "模板id为"
+ element.attribute("temp_id").getValue() + ";该模板未定义");
}
@ -265,18 +333,22 @@ public class ReadXml {
attElements.put(att.getName(), att.getValue());
}
// 存储存储模板的内容
// 获取模板的内容
String path = templetElement.getText();
// 循环遍历模板中的所有需要替换的属性
while (path.indexOf(START_SIGN) > -1) {
// 存储需要替换的标志名称
String sign = path.substring(path.indexOf(START_SIGN) + START_SIGN.length(), path.indexOf(END_SIGN));
// 判断该标志名称是否存储在attElements中若不存在则抛出异常
if (!attElements.containsKey(sign)) {
throw new NoSuchSignValueException(sign + "标志的值未记录为属性中;" + element.asXML());
//按照公式起始符号对内容进行切分遍历切分后的每一个元素
String[] texts = path.split(SPLIT_START);
for (int i = 0; i < texts.length; i++) {
//判断切分的元素是否包含公式结束符号
int index;
if ((index = texts[i].indexOf(END_SIGN)) > -1) {
//截取有效字符串对关键词进行替换
String sign = texts[i].substring(0, index);
// 判断该标志名称是否存储在attElements中若不存在则抛出异常
if (attElements.containsKey(sign)) {
// 将所有与该标志相关的全部替换为元素属性中存储的内容
path = path.replaceAll("\\$\\{" + sign + "\\}", attElements.get(sign));
}
}
// 将所有与该标志相关的全部替换为元素属性中存储的内容
path = path.replaceAll("\\$\\{" + sign + "\\}", attElements.get(sign));
}
return path;

View File

@ -88,4 +88,14 @@ public class CommonByTest {
//在获取元素前会判断元素所在窗体由于主窗体是爷爷辈窗体获取元素前会切换工资发放详情窗体
System.out.println(ce.getElement("单位名称").getWebElement().getText());
}
/**
* 用于测试外链xml
*/
@Test
public void getElementTest() {
File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml");
ce.setXmlFile(xmlFile, false);
System.out.println(ce.getElement("搜索条件", "工资单编号").getWebElement().getAttribute("type"));
}
}

View File

@ -1,39 +1,27 @@
package pres.auxiliary.selenium.xml.io;
package pres.auxiliary.work.selenium.xml;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import pres.auxiliary.work.selenium.xml.ByType;
import pres.auxiliary.work.selenium.xml.ReadXml;
/**
* <p><b>文件名</b>TestReadXml.java</p>
* <p><b>用途</b>用于测试ReadXml类</p>
* <p><b>编码时间</b>2019年10月25日下午3:14:25</p>
* <p><b>修改时间</b>2019年10月25日下午3:14:25</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class TestReadXml {
ReadXml r;
public class ReadXmlTest {
ReadXml r;
/**
* 初始化数据
*/
@BeforeClass
public void newReadXML() {
r = new ReadXml(new File("src/test/java/pres/auxiliary/selenium/xml/io/测试用xml文件.xml"));
r = new ReadXml(new File("src/test/java/pres/auxiliary/work/selenium/xml/测试用xml文件.xml"));
}
@AfterMethod
public void over(Method method) {
System.out.println("*".repeat(5) + method.getName() + "运行完毕" + "*".repeat(5));
System.out.println("*****" + method.getName() + "运行完毕" + "*****");
}
/**
@ -134,4 +122,40 @@ public class TestReadXml {
public void getIframeNameTest_RootElement() {
System.out.println(r.getIframeName("XX控件1"));
}
/**
* 用于测试{@link ReadXml#getIframeName(String)}方法获取模板元素
*/
@Test
public void getIframeNameTest_NoPram() {
System.out.println(r.getIframeName("XX控件12"));
}
/**
* 用于测试{@link ReadXml#getValue(String, ByType)}方法未查找到替换的属性
*/
@Test
public void getValueTest_NoPram() {
System.out.println(r.getValue("XX控件12", ByType.XPATH));
System.out.println(r.getValue("窗体3", ByType.XPATH));
}
/**
* 用于测试{@link ReadXml#getValue(String, ByType)}方法外链关键词
*/
@Test
public void getValueTest_Link() {
ArrayList<String> link = new ArrayList<>();
link.add("测试1");
link.add("测试2");
link.add("测试3");
//XXX模板控件1[@X='${src}']/div[@name='${name}']
System.out.println(r.getValue("XX控件13", ByType.XPATH, link));
System.out.println(r.getValue("窗体3", ByType.XPATH, link));
//XXX模板控件1[@X='${src}']/div[@name='${name}']/div[@is='${str1}' and text()='${str1}']
System.out.println(r.getValue("XX控件14", ByType.XPATH, link));
//XXX模板控件1[@X='${src}']/div[@name='${name}']/div[@is='${str1}' and text()='${src}']/span[text()='${str2}']/span[id='${aaaa}']
System.out.println(r.getValue("XX控件15", ByType.XPATH, link));
}
}