修改元素获取方式
This commit is contained in:
parent
95790ae4d9
commit
34b01d4796
16
pom.xml
16
pom.xml
|
@ -102,6 +102,13 @@
|
|||
<version>5.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库连接依赖包 -->
|
||||
<dependency>
|
||||
<groupId>com.github.noraui</groupId>
|
||||
<artifactId>ojdbc7</artifactId>
|
||||
<version>12.1.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- HttpClient 用于接口测试 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
@ -138,5 +145,14 @@
|
|||
<version>1.9.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok注解生成get/set方法依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package pres.auxiliary.directory.exception;
|
||||
|
||||
/**
|
||||
* 该异常为传入的文件夹路径不正确时抛出的异常,继承RuntimeException
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class IncorrectDirectoryException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public IncorrectDirectoryException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectDirectoryException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectDirectoryException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectDirectoryException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectDirectoryException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package pres.auxiliary.directory.exception;
|
||||
|
||||
/**
|
||||
* 该异常在未指定文件路径或者文件名时抛出的异常,继承RuntimeException
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class UndefinedDirectoryException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UndefinedDirectoryException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public UndefinedDirectoryException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public UndefinedDirectoryException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public UndefinedDirectoryException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public UndefinedDirectoryException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
package pres.auxiliary.directory.operate;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface.AddSeparatorProcessor;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface.FormatSeparatorProcessor;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface.RelativeToAbsoluteProcessor;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
|
||||
/**
|
||||
* 该类为创建文件工具类,通过该类可辅助创建文件
|
||||
*
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
public class MakeDirectory {
|
||||
// 该属性用于存储文件的路径字符串
|
||||
private static StringBuilder savePath = new StringBuilder("C:\\AutoTest\\");
|
||||
|
||||
/**
|
||||
* 私有构造,禁止创建对象
|
||||
*/
|
||||
private MakeDirectory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回文件定位的路径
|
||||
*
|
||||
* @return 返回在类中存储的文件路径
|
||||
*/
|
||||
public static String getSavePath() {
|
||||
return savePath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置文件夹的根路径
|
||||
*
|
||||
* @param savePath
|
||||
* 传入的新文件夹目录
|
||||
*/
|
||||
public static void setSavePath(String savePath) {
|
||||
// 将传入的参数进行格式化
|
||||
StringBuilder sb = new StringBuilder(savePath);
|
||||
sb = formatPath(sb);
|
||||
|
||||
// 判断格式化后的文件路径格式是否符合windonws下文件路径的命名规则,不符合则抛出异常
|
||||
if (!isPath(sb.toString())) {
|
||||
System.out.println(sb.toString());
|
||||
throw new IncorrectDirectoryException("不合理的文件夹路径,文件路径:"
|
||||
+ sb.toString());
|
||||
}
|
||||
|
||||
// 判断传入的路径是否只是硬盘的根目录,若是,则加上AutoTest文件夹
|
||||
if (isDisk(sb.toString())) {
|
||||
// 判断传入的硬盘根目录中是否包含文件夹分隔符“\\”,若不包含,则在后面加上
|
||||
if (sb.indexOf("\\") < 0) {
|
||||
sb.append("\\");
|
||||
}
|
||||
// 补上AutoTest文件夹
|
||||
sb.append("AutoTest\\");
|
||||
}
|
||||
|
||||
// 将文件路径设置入属性中
|
||||
MakeDirectory.savePath = sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于判断传入的路径输入是否正确
|
||||
*
|
||||
* @param path
|
||||
* 传入的文件路径
|
||||
* @return 返回路径是否正确
|
||||
*/
|
||||
public static boolean isPath(String path) {
|
||||
// 判断path是否为空,为空则返回false
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断path的内容是否为空,为空则返回false
|
||||
if ("".equals(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断path中的内容是否为满足路径的要求,不满足则返回false
|
||||
// 可匹配相对路径和绝对路径
|
||||
// 正则中只检测windows下创建文件夹或文件时不允许输入的字符
|
||||
if (!path.matches("^([A-z]:\\\\)?([^ :\\*\\?<\">|\\/\\\\]+?(\\\\)?)*$")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 若能满足上述条件,则返回true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于判断传入的参数是否符合在windows下文件名的命名规则(不判断后缀名)
|
||||
*
|
||||
* @param fileName
|
||||
* 传入的待判断的文件夹名称
|
||||
* @return 返回判断的结果
|
||||
*/
|
||||
public static boolean isFileName(String fileName) {
|
||||
// 判断path是否为空,为空则返回false
|
||||
if (fileName == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断path的内容是否为空,为空则返回false
|
||||
if ("".equals(fileName)) {
|
||||
return false;
|
||||
}
|
||||
// 通过正则判断文件名中是否包含windows不允许输入的特殊字符,并匹配在传入的文件名中是否至少包含一个“.”,若符合正则,则返回true
|
||||
if (fileName.matches("^([^:\\*\\?<\">|\\/\\\\])+?$")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 若未通过判断,则返回false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于判断路径是否是硬盘的根目录
|
||||
*
|
||||
* @param path
|
||||
* 传入的路径
|
||||
* @return 返回判断的结果
|
||||
*/
|
||||
public static boolean isDisk(String path) {
|
||||
// 判断path是否为空,为空则返回false
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断path的内容是否为空,为空则返回false
|
||||
if ("".equals(path)) {
|
||||
return false;
|
||||
}
|
||||
// 匹配只有盘符时的正则
|
||||
if (path.matches("^[A-z]:(\\\\)?$")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 若未通过判断,则返回false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法将对传入文件路径进行三种处理
|
||||
* <ol>
|
||||
* <li>将所有的分隔符“/”改为“\\”</li>
|
||||
* <li>末尾未添加分隔符的加上“\\”</li>
|
||||
* <li>将传入的相对路径改为绝对路径</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param path
|
||||
* 传入的文件路径,为StringBuilder对象
|
||||
* @return 返回格式化后的路径,为StringBuilder对象
|
||||
*/
|
||||
public static StringBuilder formatPath(StringBuilder path) {
|
||||
// 创建处理链
|
||||
ProcessorChain pc = new ProcessorChain();
|
||||
// 添加处理器
|
||||
pc.add(new FormatSeparatorProcessor());
|
||||
pc.add(new RelativeToAbsoluteProcessor());
|
||||
pc.add(new AddSeparatorProcessor());
|
||||
|
||||
// 返回格式化后的路径
|
||||
return pc.doProcessor(path, pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于创建使用辅助包时需要创建的文件夹
|
||||
*/
|
||||
public static void createAllFolder() {
|
||||
// TODO 创建日志文件
|
||||
// 创建文件夹,先判断文件夹是否已被创建,未被创建,则创建文件夹
|
||||
// 创建根文件夹
|
||||
File f = new File(savePath.toString());
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放测试报告的文件夹
|
||||
f = new File(savePath.toString() + "Report");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放Bug汇总表的文件夹
|
||||
f = new File(savePath.toString() + "BugSummarySheet");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放自动化运行结果的文件夹
|
||||
f = new File(savePath.toString() + "Selenium");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放自动化运行结果截图的文件夹
|
||||
f = new File(savePath.toString() + "Selenium\\Screenshot");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放自动化运行结果日志的文件夹
|
||||
f = new File(savePath.toString() + "Selenium\\Log");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放待测页面定位方式的xml文件的文件夹
|
||||
f = new File(savePath.toString() + "Xml");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放生成的测试用例文件的文件夹
|
||||
f = new File(savePath.toString() + "Case");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
|
||||
// 创建存放浏览器下载的文件的文件夹
|
||||
f = new File(savePath.toString() + "BrowersDownload");
|
||||
if (!f.exists()) {
|
||||
f.mkdir();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface;
|
||||
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorinterface.ProcessorInterface;
|
||||
|
||||
/**
|
||||
* 该处理器用于判断路径末尾是否含有分隔符“\\”,若不包含则添加上
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class AddSeparatorProcessor implements ProcessorInterface {
|
||||
|
||||
@Override
|
||||
public StringBuilder doProcessor(StringBuilder path, ProcessorChain chain) {
|
||||
// 判断字符串的最后一位是否为含分隔符,若不为分隔符则说明路径末尾没有分隔符,则说明文件路径的末尾不含“\\”,需要再添加
|
||||
if (path.lastIndexOf("\\") != (path.length() - 1)) {
|
||||
path.append("\\");
|
||||
}
|
||||
|
||||
chain.doProcessor(path, chain);
|
||||
// 返回文件路径
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AddSeparatorProcessor";
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface;
|
||||
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorinterface.ProcessorInterface;
|
||||
|
||||
/**
|
||||
* 该类用于对传入的文件路径进行文件夹分隔符格式化的处理,处理的方法是将所有的分隔符“/”改为“\\”
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class FormatSeparatorProcessor implements ProcessorInterface {
|
||||
|
||||
@Override
|
||||
public StringBuilder doProcessor(StringBuilder path, ProcessorChain chain) {
|
||||
// 用于存储循环查询字符串得到的下标
|
||||
int i = 0;
|
||||
|
||||
// 循环,查询path中的“/”,并将“/”字符改为“\\”
|
||||
while (true) {
|
||||
// 判断字符串查询到的字符串是否为“/”,若为“/”则修改
|
||||
if ((i = path.indexOf("/")) > -1) {
|
||||
// 删除当前字符
|
||||
path.delete(i, i + 1);
|
||||
// 将字符“\\”插入到删除的位置,由于需要转译,故“\\”在存储时应为“\\\\”
|
||||
path.insert(i, "\\");
|
||||
// 继续循环
|
||||
continue;
|
||||
}
|
||||
// 若未找到字符“/”,则结束循环
|
||||
break;
|
||||
}
|
||||
|
||||
chain.doProcessor(path, chain);
|
||||
|
||||
// 返回格式化后的路径
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FormatSeparatorProcessor";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package pres.auxiliary.directory.processor.directoryprocessor.impprocessorinterface;
|
||||
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorinterface.ProcessorInterface;
|
||||
|
||||
/**
|
||||
* 该处理器用于将相对路径改为绝对路径,判断相对路径的依据是路径中是否包含字符“:”,
|
||||
* 相对路径中不可能还含有字符“:”(windows下不允许创建带“:”的字符),故若路径
|
||||
* 中含有“:”,则说明路径为绝对路径。<br/><br/>
|
||||
* <i><b>注意,使用该处理器时需要保证相对路径的命名正确</b></i>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class RelativeToAbsoluteProcessor implements ProcessorInterface {
|
||||
|
||||
@Override
|
||||
public StringBuilder doProcessor(StringBuilder path, ProcessorChain chain) {
|
||||
// 判断传入的路径是绝对路径还是相对路径,若是相对路径则在相对路径前加上当前位置
|
||||
if (path.indexOf(":") < 0) {
|
||||
path.insert(0, (System.getProperty("user.dir") + "\\"));
|
||||
}
|
||||
|
||||
chain.doProcessor(path, chain);
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RelativeToAbsoluteProcessor";
|
||||
}
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
package pres.auxiliary.directory.processor.directoryprocessor.processorchain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorinterface.ProcessorInterface;
|
||||
|
||||
|
||||
public class ProcessorChain implements ProcessorInterface {
|
||||
//用于存储处理方法的类对象
|
||||
private List<ProcessorInterface> processorChain = new ArrayList<>();
|
||||
//用于记录调用的处理器在processorChain中的下标
|
||||
private int index = -1;
|
||||
|
||||
/**
|
||||
* 该构造方法不做任何处理
|
||||
*/
|
||||
public ProcessorChain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 该构造方法用于向处理链中添加一条或多条处理器
|
||||
* @param processor 待添加的处理器
|
||||
*/
|
||||
public ProcessorChain(ProcessorInterface... processor) {
|
||||
//循环,向集合中添加处理器
|
||||
for ( ProcessorInterface p : processor ) {
|
||||
add(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向处理器链末尾添加一个处理器
|
||||
* @param processor 待添加的处理器
|
||||
* @return 返回添加状态
|
||||
*/
|
||||
public boolean add(ProcessorInterface processor) {
|
||||
return processorChain.add(processor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向处理器链指定位置添加一个处理器
|
||||
* @param index 指定的处理器链位置
|
||||
* @param processor 待添加的处理器
|
||||
*/
|
||||
public void add(int index, ProcessorInterface processor) {
|
||||
processorChain.add(index, processor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向处理器链末尾添加一组处理器
|
||||
* @param processors 待添加的处理器组
|
||||
* @return 返回添加状态
|
||||
*/
|
||||
public boolean addAll(List<ProcessorInterface> processors) {
|
||||
return processorChain.addAll(processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向处理器链指定位置添加一组处理器
|
||||
* @param index 指定的处理器链位置
|
||||
* @param processors 待添加的处理器组
|
||||
* @return 返回添加状态
|
||||
*/
|
||||
public boolean addAll(int index, List<ProcessorInterface> processors) {
|
||||
return processorChain.addAll(index, processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于移除指定位置的处理器
|
||||
* @param index 指定的位置
|
||||
* @return 返回被移除的处理器
|
||||
*/
|
||||
public ProcessorInterface remove(int index) {
|
||||
return processorChain.remove(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于移除指定的处理器
|
||||
* @param processor 指定的处理器
|
||||
* @return 返回被移除的处理器
|
||||
*/
|
||||
public boolean remove(ProcessorInterface processor) {
|
||||
return processorChain.remove(processor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回指定位置的处理器
|
||||
* @param index 指定的处理器位置
|
||||
* @return 返回对应位置的处理器
|
||||
*/
|
||||
public ProcessorInterface get(int index) {
|
||||
return processorChain.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于替换指定位置的处理器
|
||||
* @param index 指定的处理器位置
|
||||
* @param processor 待替换的处理器
|
||||
* @return 返回原处理器
|
||||
*/
|
||||
public ProcessorInterface set(int index, ProcessorInterface processor) {
|
||||
return processorChain.set(index, processor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回处理链的长度
|
||||
* @return 处理链的长度
|
||||
*/
|
||||
public int size() {
|
||||
return processorChain.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过传入的处理器名称来查找处理链中是否存在该处理器,存在则返回对应
|
||||
* 的下标,不存在则返回-1(调用该方法时需要处理器重写的toString()方法是输出类名的)
|
||||
* @param processorName 待搜索的处理器名称
|
||||
* @return 对应的下标或者-1
|
||||
*/
|
||||
public int indexOf(String processorName) {
|
||||
//循环遍历数组
|
||||
for (int i = 0; i < processorChain.size(); i++) {
|
||||
//判断每一个元素的toSting()方法得到的字符串是否存在与传入的参数相同(忽略大小写),若有相同则返回相应的下标
|
||||
if ( processorChain.get(i).toString().equalsIgnoreCase(processorName) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
//循环结束则表示未找到对应的处理器,则返回-1
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过传入处理器类对象来来查找处理链中是否存在该处理器,存在则返回对应的下标,不存在则返回-1
|
||||
* @param processor 传入的处理器类对象
|
||||
* @return 对应的下标或者-1
|
||||
*/
|
||||
public int indexOf(ProcessorInterface processor) {
|
||||
return processorChain.indexOf(processor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对所有的处理器进行处理
|
||||
* @param 传入的文件路径
|
||||
* @return 返回处理后的路径
|
||||
*/
|
||||
@Override
|
||||
public StringBuilder doProcessor(StringBuilder path, ProcessorChain chain) {
|
||||
//下标向前移动
|
||||
index++;
|
||||
if ( index == chain.size() ) {
|
||||
return null;
|
||||
}
|
||||
//调用处理器的doProcessor()对象
|
||||
processorChain.get(index).doProcessor(path, chain);
|
||||
//返回处理后的文件路径
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder("ProcessorChain [ ");
|
||||
for ( ProcessorInterface p : processorChain ) {
|
||||
s.append(p.toString());
|
||||
s.append(" ");
|
||||
}
|
||||
s.append("]");
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package pres.auxiliary.directory.processor.directoryprocessor.processorinterface;
|
||||
|
||||
import pres.auxiliary.directory.processor.directoryprocessor.processorchain.ProcessorChain;
|
||||
|
||||
/**
|
||||
* 该接口定义处理传入的文件路径的方法
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public interface ProcessorInterface {
|
||||
/**
|
||||
* 该方法用于处理传入的文件路径
|
||||
*
|
||||
* @param path
|
||||
* 指定的文件路径
|
||||
* @return 返回处理后的文件路径
|
||||
*/
|
||||
public abstract StringBuilder doProcessor(StringBuilder path, ProcessorChain chain);
|
||||
|
||||
/**
|
||||
* 重写toString()方法,用于输出类名
|
||||
* */
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
|
@ -70,9 +70,6 @@ import com.jacob.com.Dispatch;
|
|||
import com.jacob.com.Variant;
|
||||
import com.opencsv.CSVReader;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* 该类用于定义生成测试报告类共用的方法
|
||||
*
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.dom4j.io.XMLWriter;
|
|||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import pres.auxiliary.directory.exception.UndefinedDirectoryException;
|
||||
import pres.auxiliary.work.selenium.xml.ByType;
|
||||
import pres.auxiliary.work.selenium.xml.ReadXml;
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public class EasyResponse {
|
|||
|
||||
//转换为JSONObject格式,若不能转换,则responseJson为null
|
||||
try {
|
||||
responseJson = JSONObject.parseObject(responseText);
|
||||
responseJson = JSON.parseObject(responseText);
|
||||
responseType = ResponseType.JSON;
|
||||
} catch (JSONException jsonException) {
|
||||
//设置responseJson为null
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
|
@ -109,7 +110,7 @@ public class PresetString {
|
|||
*
|
||||
* @return 生成的身份证号码
|
||||
*/
|
||||
public static String IdentityCard() {
|
||||
public static String identityCard() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
RandomString rs = new RandomString("123456789");
|
||||
|
||||
|
@ -120,7 +121,7 @@ public class PresetString {
|
|||
//区县
|
||||
String[] county = {"01", "02", "03", "04", "05"};
|
||||
//生日年份前两位
|
||||
int[] year = {19, 18};
|
||||
int[] year = {19};
|
||||
|
||||
//加权数
|
||||
int[] factors = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
||||
|
@ -192,8 +193,19 @@ public class PresetString {
|
|||
}
|
||||
}
|
||||
|
||||
private static String getMobleNumber(MobleNumberType mobleNumberType) {
|
||||
/**
|
||||
* 根据运营商,生成相应运营商号段的随机号码
|
||||
* @param mobleNumberType 运营商号段枚举
|
||||
* @return 相应运营商的随机号码
|
||||
*/
|
||||
public static String mobleNumber(MobleNumberType mobleNumberType) {
|
||||
RandomString rs = new RandomString(StringMode.NUM);
|
||||
ArrayList<String> regexList = mobleNumberType.getRegex();
|
||||
|
||||
//根据运营商号码开头规则,随机选择一个号段
|
||||
String regex = regexList.get(new Random().nextInt(regexList.size()));
|
||||
//再根据号段的长度,生成相应位数的尾号
|
||||
return regex + rs.toString(11 - regex.length());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,272 +0,0 @@
|
|||
package pres.auxiliary.work.easycode.event;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
import pres.auxiliary.work.selenium.element.CommonBy;
|
||||
import pres.auxiliary.work.selenium.element.DataListBy;
|
||||
import pres.auxiliary.work.selenium.element.SelectBy;
|
||||
import pres.auxiliary.work.selenium.event.ClickEvent;
|
||||
import pres.auxiliary.work.selenium.event.TextEvent;
|
||||
|
||||
public class Event {
|
||||
/**
|
||||
* 用于进行单一元素获取
|
||||
*/
|
||||
private CommonBy commonBy;
|
||||
/**
|
||||
* 用于进行选项元素获取
|
||||
*/
|
||||
private SelectBy selectBy;
|
||||
|
||||
/**
|
||||
* 用于进行点击事件
|
||||
*/
|
||||
private ClickEvent clickEvent;
|
||||
/**
|
||||
* 用于进行文本事件
|
||||
*/
|
||||
private TextEvent textEvent;
|
||||
|
||||
/**
|
||||
* 用于执行当前需要切换的xml文件对象
|
||||
*/
|
||||
private File xmlFile;
|
||||
/**
|
||||
* 用于指向是否需要切换到顶层
|
||||
*/
|
||||
private boolean isBreakRootFrame;
|
||||
/**
|
||||
* 存储WebDriver对象
|
||||
*/
|
||||
private WebDriver driver;
|
||||
|
||||
/**
|
||||
* 初始化{@link WebDriver}对象
|
||||
* @param driver {@link WebDriver}对象
|
||||
*/
|
||||
public Event(WebDriver driver) {
|
||||
//初始化元素获取类
|
||||
commonBy = new CommonBy(driver);
|
||||
selectBy = new SelectBy(driver);
|
||||
|
||||
//初始化元素操作类
|
||||
clickEvent = new ClickEvent(driver);
|
||||
textEvent = new TextEvent(driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过{@link AbstractBrower}对象初始化{@link WebDriver}对象
|
||||
* @param brower {@link AbstractBrower}对象
|
||||
*/
|
||||
public Event(AbstractBrower brower) {
|
||||
this(brower.getDriver());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于切换相应的xml文件
|
||||
* @param xmlFile xml文件对象
|
||||
* @param isBreakRootFrame 是否切换回到顶层
|
||||
*/
|
||||
public void switchXmlFile(File xmlFile, boolean isBreakRootFrame) {
|
||||
commonBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
selectBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
|
||||
this.xmlFile = xmlFile;
|
||||
this.isBreakRootFrame = isBreakRootFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对单一元素进行点击事件
|
||||
* @param name 元素名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void click(String name, String...keys) {
|
||||
clickEvent.click(commonBy.getElement(name, keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对列表元素进行点击事件
|
||||
* @param name 元素名称
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void click(String name, int index, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
clickEvent.click(dataListBy.getElement(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对单一元素进行双击事件
|
||||
* @param name 元素名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void doubleClick(String name, String...keys) {
|
||||
clickEvent.doubleClick(commonBy.getElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对列表元素进行双击事件
|
||||
* @param name 元素名称
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void doubleClick(String name, int index, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
clickEvent.doubleClick(dataListBy.getElement(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对单一元素进行右击事件
|
||||
* @param name 元素名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void rightClick(String name, String...keys) {
|
||||
clickEvent.rightClick(commonBy.getElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对列表元素进行右击事件
|
||||
* @param name 元素名称
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void rightClick(String name, int index, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
clickEvent.rightClick(dataListBy.getElement(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对单一元素进行连续点击事件
|
||||
* @param name 元素名称
|
||||
* @param clickCount 点击次数
|
||||
* @param sleepInMillis 操作时间间隔,单位为毫秒
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void continuousClick(String name, int clickCount, long sleepInMillis, String...keys) {
|
||||
clickEvent.continuousClick(commonBy.getElement(name), clickCount, sleepInMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称对列表元素进行连续点击事件
|
||||
* @param name 元素名称
|
||||
* @param clickCount 点击次数
|
||||
* @param sleepInMillis 操作时间间隔,单位为毫秒
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
*/
|
||||
public void continuousClick(String name, int index, int clickCount, long sleepInMillis, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
clickEvent.continuousClick(dataListBy.getElement(name, index), clickCount, sleepInMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称清除单一控件的内容
|
||||
* @param name 控件名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 被清除的内容
|
||||
*/
|
||||
public String clear(String name, String...keys) {
|
||||
return textEvent.clear(commonBy.getElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称清除列表控件的内容
|
||||
* @param name 控件名称
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 被清除的内容
|
||||
*/
|
||||
public String clear(String name, int index, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
return textEvent.clear(dataListBy.getElement(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称获取单一控件指定属性的内容
|
||||
* @param name 控件名称
|
||||
* @param attributeName 属性名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 控件属性的内容
|
||||
*/
|
||||
public String getAttributeValue(String name, String attributeName, String...keys) {
|
||||
return textEvent.getAttributeValue(commonBy.getElement(name), attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称获取列表控件指定属性的内容
|
||||
* @param name 控件名称
|
||||
* @param index 元素所在下标
|
||||
* @param attributeName 属性名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 控件属性的内容
|
||||
*/
|
||||
public String getAttributeValue(String name, int index, String attributeName, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
return textEvent.getAttributeValue(dataListBy.getElement(name, index), attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称获取单一控件的内容
|
||||
* @param name 控件名称
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 控件的内容
|
||||
*/
|
||||
public String getText(String name, String...keys) {
|
||||
return textEvent.getText(commonBy.getElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称获取列表控件的内容
|
||||
* @param name 控件名称
|
||||
* @param index 元素所在下标
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 控件的内容
|
||||
*/
|
||||
public String getText(String name, int index, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
return textEvent.getText(dataListBy.getElement(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称对单一控件进行输入
|
||||
* @param name 控件名称
|
||||
* @param text 输入的内容
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 输入到控件的内容
|
||||
*/
|
||||
public String input(String name, String text, String...keys) {
|
||||
return textEvent.input(commonBy.getElement(name), text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据控件名称获取列表控件的内容
|
||||
* @param name 控件名称
|
||||
* @param index 元素所在下标
|
||||
* @param text 输入的内容
|
||||
* @param keys 需要替换的定位方式内容的关键词
|
||||
* @return 输入到控件的内容
|
||||
*/
|
||||
public String input(String name, int index, String text, String...keys) {
|
||||
DataListBy dataListBy = new DataListBy(driver);
|
||||
dataListBy.setXmlFile(xmlFile, isBreakRootFrame);
|
||||
dataListBy.add(name, keys);
|
||||
return textEvent.input(dataListBy.getElement(name, index), text);
|
||||
}
|
||||
}
|
|
@ -29,9 +29,6 @@ import org.dom4j.io.OutputFormat;
|
|||
import org.dom4j.io.SAXReader;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* 该类用于向指定的路径下生成用于上传至禅道上的测试用例模版,目前实现已基本模拟从禅道专业版上导出的
|
||||
* 模版文件,用户从禅道开源版导出csv的模块数据后,通过类中存储的方法,可实现向模块项与需求项中添加数据有效性。
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.dom4j.DocumentException;
|
|||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.directory.exception.UndefinedDirectoryException;
|
||||
import pres.auxiliary.work.old.testcase.change.CaseTab;
|
||||
import pres.auxiliary.work.old.testcase.change.Tab;
|
||||
import pres.auxiliary.work.old.testcase.templet.ZentaoExcel;
|
||||
|
|
|
@ -3,6 +3,7 @@ package pres.auxiliary.work.selenium.brower;
|
|||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -36,6 +37,8 @@ public abstract class AbstractBrower {
|
|||
* 存储打开的页面
|
||||
*/
|
||||
HashMap<String, Page> pageMap = new HashMap<String, Page>(16);
|
||||
|
||||
HashSet<String> windowHandleSet = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 用于存储WebDriver当前指向的页面信息
|
||||
|
@ -162,7 +165,9 @@ public abstract class AbstractBrower {
|
|||
overridePage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//存储当前打开窗口的handle
|
||||
windowHandleSet.add(nowPage.getHandle());
|
||||
// 切换至相应的窗口
|
||||
driver.switchTo().window(nowPage.getHandle());
|
||||
}
|
||||
|
@ -220,6 +225,14 @@ public abstract class AbstractBrower {
|
|||
|
||||
return pageList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回当前指向的窗体打开的页面{@link Page}对象
|
||||
* @return {@link Page}对象
|
||||
*/
|
||||
public Page getNowPage() {
|
||||
return nowPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于重启浏览器,若未生成WebDriver对象时(即未调用{@link #getDriver()}方法时),则方法调用无效
|
||||
|
@ -296,11 +309,13 @@ public abstract class AbstractBrower {
|
|||
public void switchWindow(String pageName) {
|
||||
try {
|
||||
driver.switchTo().window(findPageHandle(pageName));
|
||||
//切换当前指向的页面
|
||||
nowPage = pageMap.get(pageName);
|
||||
} catch (NoSuchWindowException e) {
|
||||
throw new IncorrectPageException("页面未在浏览器中打开");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用于根据页面切换页面
|
||||
*
|
||||
|
@ -311,14 +326,14 @@ public abstract class AbstractBrower {
|
|||
if (pageMap.containsKey(page.getPageName())) {
|
||||
try {
|
||||
driver.switchTo().window(page.getHandle());
|
||||
//切换当前指向的页面
|
||||
nowPage = page;
|
||||
} catch (NoSuchWindowException e) {
|
||||
throw new IncorrectPageException("页面未在浏览器中打开");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 用于切换到当前页面
|
||||
*/
|
||||
|
@ -328,7 +343,100 @@ public abstract class AbstractBrower {
|
|||
switchWindow(nowPage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于切换到弹窗上,当浏览器存在多个弹窗时,该方法无法保证能切换至理想的窗口,
|
||||
* 但调用该方法后,其弹窗会作为{@link Page}类对象进行存储,其页面名称为当前窗口的
|
||||
* handle值,若切换的窗口非理想的窗口,则可以多次调用该方法,直至切换至理想的窗口
|
||||
* 为止。若当前不存在弹窗,则返回false,若切换弹窗成功,则返回true
|
||||
*
|
||||
* @return 是否成功切换弹窗
|
||||
*/
|
||||
public boolean switchPopuWindow() {
|
||||
//判断当前是否存在弹窗,若不存在,则直接失败
|
||||
if (!hasPopuWindow()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//若存在弹窗,则获取获取当前所有窗口的handle,获取其中一个弹窗的handle值进行存储
|
||||
String popuHandle = getPopuHandle(driver.getWindowHandles());
|
||||
//切换弹窗
|
||||
driver.switchTo().window(popuHandle);
|
||||
//将弹窗转换为Page类对象,存储至pageMap中,以避免存在多个弹窗时其他弹窗无法被切换的情况
|
||||
Page popuPage = new Page(driver.getCurrentUrl(), popuHandle);
|
||||
popuPage.setHandle(popuHandle);
|
||||
popuPage.setAssertTitle(driver.getTitle());
|
||||
|
||||
//存储弹窗
|
||||
pageMap.put(popuHandle, popuPage);
|
||||
//将当前页面指向到弹窗页面上
|
||||
nowPage = popuPage;
|
||||
|
||||
//返回切换弹窗成功
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于判断当前浏览器中是否存在弹窗(未被存储的浏览器标签)。注意,若在
|
||||
* 浏览器上自行打开的标签,其也会被计算为弹窗
|
||||
* @return 是否存在弹窗
|
||||
*/
|
||||
public boolean hasPopuWindow() {
|
||||
//获取当前浏览器上的窗口handle
|
||||
Set<String> nowWindowHandleSet = driver.getWindowHandles();
|
||||
//移除被手动关闭的标签
|
||||
removeClosePage(nowWindowHandleSet);
|
||||
//若nowWindowHandleSet中的数量与windowHandleSet不一致,则可认为存在弹窗
|
||||
return nowWindowHandleSet.size() != windowHandleSet.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 定位到弹框上并且点击确定按钮,并返回弹框上的文本
|
||||
*
|
||||
* @return 弹框上的文本
|
||||
*/
|
||||
public String alertAccept() {
|
||||
String text = alertGetText();
|
||||
driver.switchTo().alert().accept();
|
||||
|
||||
return text;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 定位到弹框上并且点击取消按钮,并返回弹框上的文本
|
||||
*
|
||||
* @return 弹框上的文本
|
||||
*/
|
||||
public String alertDimiss() {
|
||||
String text = alertGetText();
|
||||
driver.switchTo().alert().dismiss();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定位到弹框上并且在其文本框中输入信息
|
||||
*
|
||||
* @param content 需要输入的信息
|
||||
* @return 弹框上的文本
|
||||
*/
|
||||
public String alertInput(String content) {
|
||||
String text = alertGetText();
|
||||
driver.switchTo().alert().sendKeys("");
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取弹框上的文本
|
||||
*
|
||||
* @return 弹框上的文本
|
||||
*/
|
||||
public String alertGetText() {
|
||||
return driver.switchTo().alert().getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于新增一个标签页,并打开指定站点
|
||||
*
|
||||
|
@ -373,7 +481,7 @@ public abstract class AbstractBrower {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return newHandle;
|
||||
}
|
||||
|
||||
|
@ -423,4 +531,33 @@ public abstract class AbstractBrower {
|
|||
// 若类中未存储相应page,则返回null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于在pageMap中移除已被关闭的浏览器标签,该方法主要用于清除手动关闭的标签
|
||||
* @param handleList 当前浏览器存储的标签值
|
||||
*/
|
||||
private void removeClosePage(Set<String> handleList) {
|
||||
ArrayList<String> removeKeyList = new ArrayList<>();
|
||||
//遍历pageMap,若其handle值不存在于handleList中,则记录需要移除的key值
|
||||
pageMap.forEach((key, value) -> {
|
||||
if (!handleList.contains(value.getHandle())) {
|
||||
removeKeyList.add(key);
|
||||
}
|
||||
});
|
||||
|
||||
//遍历removeKeyList,在pageMap中移除相应的key
|
||||
removeKeyList.forEach(key -> {
|
||||
pageMap.remove(key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回当前浏览器中其中一个弹窗的handle值,当存在多个弹窗时
|
||||
* 该方法不保证返回的handle为理想的handle值
|
||||
* @param handleList 当前浏览器中所有的窗口handle集合
|
||||
* @return 其中一个弹窗的handle值
|
||||
*/
|
||||
private String getPopuHandle(Set<String> handleSet) {
|
||||
return handleSet.stream().filter(handle -> findPage(handle) == null).findAny().get();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -110,10 +110,12 @@ public class SelectBy extends MultiBy {
|
|||
* @param fristIsEmpty 首个选项是否为不可选择的选项或者文本为空的选项
|
||||
* @see #add(String)
|
||||
*/
|
||||
/*
|
||||
public void add(String name, boolean fristIsEmpty) {
|
||||
this.fristIsEmpty = fristIsEmpty;
|
||||
add(name);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用于添加选项并指明首个选项是否为不可选择的选项或者文本为空的选项,其他效果与{@link #add(String, ByType)}一致
|
||||
|
@ -122,10 +124,12 @@ public class SelectBy extends MultiBy {
|
|||
* @param fristIsEmpty 首个选项是否为不可选择的选项或者文本为空的选项
|
||||
* @see #add(String, ByType)
|
||||
*/
|
||||
/*
|
||||
public void add(String name, ByType byType, boolean fristIsEmpty) {
|
||||
this.fristIsEmpty = fristIsEmpty;
|
||||
add(name, byType);
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void add(String name, ByType byType, String... links) {
|
||||
|
@ -147,11 +151,13 @@ public class SelectBy extends MultiBy {
|
|||
* @param fristIsEmpty 首个选项是否为不可选择的选项或者文本为空的选项
|
||||
* @param links 替换词语
|
||||
*/
|
||||
/*
|
||||
public void add(String name, ByType byType, boolean fristIsEmpty, String... links) {
|
||||
this.fristIsEmpty = fristIsEmpty;
|
||||
add(name, byType, links);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 可用于指明首行是否为空选项,其他说明可参考{@link #add(String, String...)}
|
||||
|
@ -159,11 +165,21 @@ public class SelectBy extends MultiBy {
|
|||
* @param fristIsEmpty 首个选项是否为不可选择的选项或者文本为空的选项
|
||||
* @param links 替换词语
|
||||
*/
|
||||
/*
|
||||
public void add(String name, boolean fristIsEmpty, String... links) {
|
||||
this.fristIsEmpty = fristIsEmpty;
|
||||
add(name, null, links);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 设置首个选项是否为不可选择的选项
|
||||
* @param fristIsEmpty 首个选项是否为不可选择
|
||||
*/
|
||||
public void setFristIsEmpty(boolean fristIsEmpty) {
|
||||
this.fristIsEmpty = fristIsEmpty;
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(ElementInformation elementInformation) {
|
||||
|
|
|
@ -0,0 +1,329 @@
|
|||
package pres.auxiliary.work.selenium.element.copy;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
import pres.auxiliary.work.selenium.element.UnrecognizableLocationModeException;
|
||||
import pres.auxiliary.work.selenium.xml.ByType;
|
||||
import pres.auxiliary.work.selenium.xml.ReadXml;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>AbstractElement.java</p>
|
||||
* <p><b>用途:</b></p>
|
||||
* <p><pre>
|
||||
* 对辅助化测试工具selenium的获取元素代码进行的二次封装,通过类中提供的方法以及配合相应存储元素的
|
||||
* xml文件,以更简便的方式对页面元素进行获取,减少编程时的代码量。
|
||||
* </pre></p>
|
||||
* <p><b>编码时间:</b>2020年4月25日 下午4:18:37</p>
|
||||
* <p><b>修改时间:</b>2020年4月25日 下午4:18:37</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*/
|
||||
public abstract class AbstractBy {
|
||||
/**
|
||||
* 用于指向存储控件定位方式的xml文件,设置属性为静态,用于在编写脚本时不需要频繁切换xml文件
|
||||
*/
|
||||
static ReadXml xml;
|
||||
|
||||
/**
|
||||
* 用于存储浏览器对象
|
||||
*/
|
||||
AbstractBrower brower;
|
||||
/**
|
||||
* 存储单个控件的等待时间
|
||||
*/
|
||||
private HashMap<String, Long> controlWaitTime = new HashMap<String, Long>();
|
||||
|
||||
/**
|
||||
* 用于存储元素通用的等待时间,默认5秒
|
||||
*/
|
||||
private long waitTime = 5;
|
||||
|
||||
/**
|
||||
* 通过浏览器对象{@link AbstractBrower}进行构造
|
||||
* @param brower {@link AbstractBrower}对象
|
||||
*/
|
||||
public AbstractBy(AbstractBrower brower) {
|
||||
this.brower = brower;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置元素查找等待时间,默认时间为5秒
|
||||
*
|
||||
* @param waitTime 事件等待时间
|
||||
*/
|
||||
public void setWaitTime(long waitTime) {
|
||||
this.waitTime = waitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对符合正则表达式的控件名称设置等待时间
|
||||
*
|
||||
* @param regex 正则表达式
|
||||
* @param waitTime 等待时间
|
||||
*/
|
||||
public void setContorlWaitTime(String regex, long waitTime) {
|
||||
controlWaitTime.put(regex, waitTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置指向存储元素定位方式的xml文件对象,并根据传参,判断窗体是否需要回到顶层
|
||||
* @param xmlFile 存储元素定位方式的xml文件对象
|
||||
* @param isBreakRootFrame 是否需要将窗体切回到顶层
|
||||
*/
|
||||
public void setXmlFile(File xmlFile) {
|
||||
if (xml == null) {
|
||||
xml = new ReadXml(xmlFile);
|
||||
} else {
|
||||
xml.setXmlPath(xmlFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用于根据传入的控件名称或定位方式,对控件在页面上定位,返回其WebElement对象。形参可以传入在xml文件中元素的名称,
|
||||
* 亦可以传入页面元素的定位方式,但目前识别只支持xpath和css两种方式。
|
||||
* 该方法获取的是一组元素,可用于对列表元素事件中。
|
||||
* </p>
|
||||
* <p>
|
||||
* 元素识别判断方式按照以下步骤进行:<br>
|
||||
* 1.先对xml文件进行扫描,若存在该元素对应的标签,则读取xml文件的定位方式,并识别有效的定位方式一一匹配,直到正确为止;<br>
|
||||
* 2.若在xml文件中查找不到该元素,则按照xpath和css的规则进行匹配,直到判断出该元素的定位方式位置;<br>
|
||||
* 3.若仍找不到元素,则抛出UnrecognizableLocationModeException
|
||||
* </p>
|
||||
*
|
||||
* @param name 元素名称或元素的定位方式
|
||||
* @return 返回页面一组元素的定位方式对象
|
||||
* @throws TimeoutException 元素在指定时间内未查找到时,抛出的异常
|
||||
* @throws UnrecognizableLocationModeException 元素无法识别时抛出的异常
|
||||
*/
|
||||
List<By> recognitionElement(ElementInformation elementInformation) {
|
||||
if (isXmlElement(elementInformation.name)) {
|
||||
//若指定了xml文件,且传入的元素名称存在与xml文件中,则判断元素相应的定位方式及定位内容
|
||||
return recognitionXmlElement(elementInformation);
|
||||
} else {
|
||||
//若未指定xml文件,或者在xml文件中无法查到相应的元素时,则将name的值赋给value,且根据value判断相应定位方式
|
||||
return recognitionCommonElement(elementInformation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取普通元素的By对象
|
||||
* @param elementInformation 元素信息类对象
|
||||
* @return 元素信息指向的By对象
|
||||
*/
|
||||
private List<By> recognitionCommonElement(ElementInformation elementInformation) {
|
||||
List<By> byList = new ArrayList<>();
|
||||
|
||||
//判断传入的ByType对象是否为null
|
||||
if (elementInformation.byType == null) {
|
||||
byList.addAll(getCommonElementBy(elementInformation.name));
|
||||
} else {
|
||||
byList.add(valueToBy(elementInformation.name, elementInformation.byType));
|
||||
}
|
||||
|
||||
return byList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取xml文件内元素的By对象
|
||||
* @param elementInformation 元素信息类对象
|
||||
* @return 元素信息指向的By对象
|
||||
*/
|
||||
private List<By> recognitionXmlElement(ElementInformation elementInformation) {
|
||||
//查找元素的父层级结构
|
||||
elementInformation.iframeList = getParentFrameName(elementInformation.name);
|
||||
|
||||
//存储元素的By对象集合
|
||||
List<By> byList = new ArrayList<>();
|
||||
|
||||
//判断传入的ByType对象是否为null
|
||||
if (elementInformation.byType == null) {
|
||||
byList.addAll(getXmlElementBy(elementInformation.name, elementInformation.linkKeyList));
|
||||
} else {
|
||||
byList.add(xml.getBy(elementInformation.name, elementInformation.byType, elementInformation.linkKeyList));
|
||||
}
|
||||
|
||||
return byList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回控件的等待时间,若设置单个控件的等待时间(使用{@link #setContorlWaitTime(String, long)}方法设置),
|
||||
* 则返回设置的控件等待时间;若未设置单个控件的等待时间,则返回设置的通用等待时间(使用{@link #setWaitTime(long)}方法)
|
||||
* ;若未对通用时间进行设置,则返回默认时间({@link #waitTime})
|
||||
* @param name 控件名称
|
||||
* @return 相应控件的等待时间
|
||||
* @see #setContorlWaitTime(String, long)
|
||||
* @see #setWaitTime(long)
|
||||
*/
|
||||
long getWaitTime(String name) {
|
||||
for (String regex : controlWaitTime.keySet()) {
|
||||
if (Pattern.compile(regex).matcher(name).matches()) {
|
||||
return controlWaitTime.get(regex);
|
||||
}
|
||||
}
|
||||
|
||||
return waitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于获取元素在xml文件中所有的父窗体,并以集合的形式返回,存储的顺序为父窗体在前,子窗体在后,若当前元素没有窗体,
|
||||
* 则集合的长度为0
|
||||
* @param name 元素在xml文件中的名称
|
||||
* @return 元素在xml文件中所有的父窗体集合
|
||||
*/
|
||||
List<String> getParentFrameName(String name) {
|
||||
//存储获取到的父层窗体名称
|
||||
List<String> nameList = new ArrayList<String>();
|
||||
|
||||
//获取元素所在窗体的名称
|
||||
String iframeName = xml.getIframeName(name);
|
||||
//循环,判断窗体是否存在(方法返回不为空),若存在,则再将父窗体进行存储
|
||||
while(!iframeName.isEmpty()) {
|
||||
//存储窗体
|
||||
nameList.add(iframeName);
|
||||
//再以当前窗体的名称再次获取该窗体的父窗体
|
||||
iframeName = xml.getIframeName(iframeName);
|
||||
}
|
||||
|
||||
return nameList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据传入的参数,识别非xml文件内的元素定位方式。
|
||||
* 该方法能快速识别xpath定位方式以及绝对css定位方式,若不是以上两种定位方式
|
||||
* 则会遍历所有的定位方式,此时会降低运行速度,建议在不是以上两种定位方式的
|
||||
* 情况下,直接指定元素的定位方式,以提高效率
|
||||
*/
|
||||
List<By> getCommonElementBy(String value) {
|
||||
List<By> byList = new ArrayList<>();
|
||||
// 如果抛出元素名称查找不到的的异常,则对应匹配xpath和绝对css路径两种定位方式
|
||||
// 匹配xpath定位,判定方法,判断text的第一个字符是否是“/”
|
||||
//由于是识别普通元素,非xml元素其value就是元素的名称name, 故获取等待时间时可直接将value传入
|
||||
if (value.indexOf("/") == 0) {
|
||||
byList.add(valueToBy(value, ByType.XPATH));
|
||||
} else if (value.indexOf("html") == 0) {
|
||||
//在页面中查找元素,若元素能找到,则结束查找
|
||||
byList.add(valueToBy(value, ByType.CSS));
|
||||
} else {
|
||||
//若元素无法识别,则将所有的定位类型(排除xpath类型)与之进行对比,直到在页面上找到元素为止
|
||||
for(ByType type : ByType.values()) {
|
||||
if (type == ByType.XPATH) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byList.add(valueToBy(value, type));
|
||||
}
|
||||
}
|
||||
|
||||
return byList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置xml文件内的元素的定位方式及定位内容
|
||||
*/
|
||||
List<By> getXmlElementBy(String name, List<String> linkList) {
|
||||
//用于存储从xml文件中读取到的所有内容,并封装成By对象
|
||||
List<By> byList = new ArrayList<>();
|
||||
// 循环,逐个在页面上配对有效的标签对应的定位方式
|
||||
for (ByType mode : xml.getElementMode(name)) {
|
||||
byList.add(valueToBy(xml.getValue(name, mode, linkList), mode));
|
||||
}
|
||||
|
||||
return byList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据元素的参数,返回元素的By对象
|
||||
* @return 元素的By对象
|
||||
*/
|
||||
By valueToBy(String value, ByType byType) {
|
||||
//根据元素的定位方式,对定位内容进行选择,返回相应的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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于判断元素是否为xml文件内的元素
|
||||
* @param name 元素名称
|
||||
* @return 是否为xml文件内的元素
|
||||
*/
|
||||
boolean isXmlElement(String name) {
|
||||
return (xml != null && xml.isElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>AbstractElement.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 存储获取元素时的信息
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年5月9日上午7:57:24</p>
|
||||
* <p><b>修改时间:</b>2020年5月22日上午8:18:39</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.1
|
||||
* @since JDK 1.8
|
||||
*
|
||||
*/
|
||||
class ElementInformation {
|
||||
/**
|
||||
* 存储元素的名称或定位内容
|
||||
*/
|
||||
public String name;
|
||||
/**
|
||||
* 存储元素的定位方式
|
||||
*/
|
||||
public ByType byType;
|
||||
/**
|
||||
* 用于标记元素的类型
|
||||
*/
|
||||
public ElementType elementType;
|
||||
/**
|
||||
* 用于存储在xml文件中需要外链的词语
|
||||
*/
|
||||
public List<String> linkKeyList;
|
||||
/**
|
||||
* 用于存储元素的父层结构
|
||||
*/
|
||||
public List<String> iframeList;
|
||||
/**
|
||||
* 构造元素信息
|
||||
* @param name 元素名称
|
||||
* @param byType 元素定位的By类型,枚举
|
||||
* @param elementType 元素类型,枚举
|
||||
* @param linkKeyList xml文件中需要外部替换的词语
|
||||
*/
|
||||
public ElementInformation(String name, ByType byType, ElementType elementType, List<String> linkKeyList) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.byType = byType;
|
||||
this.elementType = elementType;
|
||||
this.linkKeyList = linkKeyList;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package pres.auxiliary.work.selenium.element.copy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
import pres.auxiliary.work.selenium.xml.ByType;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>CommonElement.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 提供在辅助化测试中,对页面单一元素获取的方法。类中获取元素的方法兼容传入定位方式对
|
||||
* 元素进行查找,建议使用xml对页面元素的定位方式进行存储,以简化编码时的代码量,也便于
|
||||
* 对代码的维护
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年4月26日下午10:34:55</p>
|
||||
* <p><b>修改时间:</b>2020年4月26日下午10:34:55</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 8
|
||||
*
|
||||
*/
|
||||
public class CommonBy extends AbstractBy {
|
||||
/**
|
||||
* 通过浏览器对象{@link AbstractBrower}进行构造
|
||||
* @param brower {@link AbstractBrower}对象
|
||||
*/
|
||||
public CommonBy(AbstractBrower brower) {
|
||||
super(brower);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据xml文件中元素的名称,返回对应的{@link Element}对象。该方法亦可传入元素
|
||||
* 定位内容,通过遍历所有的定位方式,在页面上查找元素,来获取元素的WebElement对象。
|
||||
* 建议传入的定位内容为xpath路径或绝对的css路径,若非这两路径,则在识别元素时会很慢,降低
|
||||
* 程序运行速度。若非xml文件中的元素,且不是xpath路径或绝对的css路径,建议使用{@link #getElement(String, ByType)}方法
|
||||
* @param name 元素的名称或元素定位内容
|
||||
* @return {@link Element}对象
|
||||
*/
|
||||
public Element getElement(String name) {
|
||||
return getElement(new ElementInformation(name, null, ElementType.COMMON_ELEMENT, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据xml文件中元素的名称,与定位方式,返回对应的{@link Element}对象。该方法亦可传入元素
|
||||
* 定位内容,并根据定位方式,对页面数据进行查找
|
||||
* @param name 元素的名称或元素定位内容
|
||||
* @return {@link Element}对象
|
||||
*/
|
||||
public Element getElement(String name, ByType byType) {
|
||||
return getElement(new ElementInformation(name, byType, ElementType.COMMON_ELEMENT, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据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, Arrays.asList(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(new ElementInformation(name, null, ElementType.COMMON_ELEMENT, Arrays.asList(links)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素的底层方法
|
||||
* @param elementInformation 元素信息类对象
|
||||
* @return WebElement对象
|
||||
*/
|
||||
private Element getElement(ElementInformation elementInformation) {
|
||||
Element element = new Element(brower, elementInformation.name, ElementType.COMMON_ELEMENT, 0);
|
||||
element.setWaitTime(getWaitTime(elementInformation.name));
|
||||
element.setByList(recognitionElement(elementInformation));
|
||||
|
||||
//构造元素的父层元素,若元素不存在窗体结构,则不进行构造
|
||||
if (elementInformation.iframeList != null && elementInformation.iframeList.size() != 0) {
|
||||
//指向当前元素,用于设置当前元素的父层窗体元素
|
||||
Element childElement = element;
|
||||
//使用Iterator
|
||||
Iterator<String> it = elementInformation.iframeList.iterator();
|
||||
//循环,一一设置父层结构
|
||||
do {
|
||||
//获取父层的元素的名称
|
||||
String iframeName = it.next();
|
||||
//构造父层元素
|
||||
Element iframeElement = new Element(brower, iframeName, ElementType.COMMON_ELEMENT, 0);
|
||||
//设置父层元素的获取方式及等待时间
|
||||
iframeElement.setWaitTime(getWaitTime(iframeName));
|
||||
iframeElement.setByList(getXmlElementBy(iframeName, null));
|
||||
//设置父层
|
||||
childElement.setIframeElement(iframeElement);
|
||||
//将子元素指向父层元素,以获取下一层窗体元素
|
||||
childElement = iframeElement;
|
||||
} while(it.hasNext());
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
package pres.auxiliary.work.selenium.element.copy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Element.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 用于返回和查找页面元素,以方便在元素过期时能进行重新获取
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年5月18日上午8:39:05</p>
|
||||
* <p><b>修改时间:</b>2020年5月18日上午8:39:05</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 8
|
||||
*
|
||||
*/
|
||||
public class Element {
|
||||
/**
|
||||
* 存储元素
|
||||
*/
|
||||
private WebElement element = null;
|
||||
/**
|
||||
* 存储查找元素的By对象
|
||||
*/
|
||||
private List<By> byList;
|
||||
/**
|
||||
* 用于存储窗体元素
|
||||
*/
|
||||
private Element iframeElement = null;
|
||||
/**
|
||||
* 用于存储当前已指向的窗体
|
||||
*/
|
||||
private static ArrayList<Element> iframeElementList = new ArrayList<>();
|
||||
/**
|
||||
* 存储获取需要获取的元素下标
|
||||
*/
|
||||
private int elementIndex;
|
||||
|
||||
/**
|
||||
* 存储WebDriver对象,以查找相应元素
|
||||
*/
|
||||
private WebDriver driver;
|
||||
/**
|
||||
* 用于存储当前打开的浏览器对象
|
||||
*/
|
||||
// private AbstractBrower brower;
|
||||
/**
|
||||
* 用于存储元素的名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 标记元素的类型,以用于重新获取时
|
||||
*/
|
||||
private ElementType elementType;
|
||||
|
||||
/**
|
||||
* 用于存储元素查找等待时间,默认3秒
|
||||
*/
|
||||
private long waitTime = 3;
|
||||
|
||||
/**
|
||||
* TODO 确定构造后添加注释
|
||||
*/
|
||||
public Element(AbstractBrower brower, String name, ElementType elementType, int elementIndex) {
|
||||
super();
|
||||
//存储Driver对象
|
||||
this.driver = brower.getDriver();
|
||||
this.name = name;
|
||||
this.elementType = elementType;
|
||||
this.elementIndex = elementIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据存储的元素信息,在相应的页面中查找,并返回一个{@link WebElement}对象
|
||||
* @return {@link WebElement}对象
|
||||
*/
|
||||
public WebElement getWebElement() {
|
||||
//切换窗体
|
||||
autoSwitchIframe();
|
||||
|
||||
//若element为null,则对元素进行一次查找
|
||||
if (element == null) {
|
||||
findElemen();
|
||||
}
|
||||
|
||||
//返回相应的内容
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置元素定位的{@link By}对象集合,调用该方法后将清空原存储的内容,重新添加{@link By}对象集合
|
||||
* @param byList {@link By}对象集合
|
||||
*/
|
||||
public void setByList(List<By> byList) {
|
||||
this.byList = byList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置元素的父层窗体
|
||||
* @param iframeElement 元素的父层窗体
|
||||
*/
|
||||
public void setIframeElement(Element iframeElement) {
|
||||
this.iframeElement = iframeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素所在的窗体元素对象
|
||||
* @return 元素所在的窗体元素对象
|
||||
*/
|
||||
public Element getIframeElement() {
|
||||
return iframeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回当前存储的{@link WebDriver}对象
|
||||
* @return {@link WebDriver}对象
|
||||
*/
|
||||
public WebDriver getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素名称
|
||||
* @return 元素名称
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置元素查询等待时间,该时间为元素每个{@link By}对象在页面查询的时间。注意,若添加
|
||||
* 过多无效的{@link By}对象,会导致查询等待时间过长
|
||||
* @param waitTime 元素查询等待时间
|
||||
*/
|
||||
public void setWaitTime(long waitTime) {
|
||||
this.waitTime = waitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素在列表中的下标
|
||||
* @return 元素下标
|
||||
*/
|
||||
public int getElementIndex() {
|
||||
return elementIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素所在的所有父窗体
|
||||
* @return 父窗体集合
|
||||
*/
|
||||
public ArrayList<Element> getAllIframe() {
|
||||
//存储当前元素的所在的所有窗体
|
||||
ArrayList<Element> iframeList = new ArrayList<>();
|
||||
|
||||
//用于指向元素所在的窗体
|
||||
Element iframe = iframeElement;
|
||||
//若窗体元素不为null,则循环
|
||||
while(iframe != null) {
|
||||
//存储窗体元素
|
||||
iframeList.add(iframe);
|
||||
//向下探寻是否存在下一级窗体元素
|
||||
iframe = iframe.getIframeElement();
|
||||
}
|
||||
|
||||
//若iframeList中未存储元素,则不进行倒叙
|
||||
if (iframeList.size() != 0) {
|
||||
//由于存储顺序为子窗体在前,不符合切换窗体的顺序,故需要对集合进行倒叙操作
|
||||
Collections.reverse(iframeList);
|
||||
}
|
||||
|
||||
return iframeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于将窗体切换至顶层
|
||||
*/
|
||||
public void switchRootIframe() {
|
||||
//切换窗体至顶层
|
||||
driver.switchTo().defaultContent();
|
||||
//将iframeElementList中的内容清空
|
||||
iframeElementList.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于向下切换一层窗体
|
||||
* @param iframeElement 窗体元素类对象
|
||||
*/
|
||||
public void switchIframe(Element iframeElement) {
|
||||
//切换窗体
|
||||
driver.switchTo().frame(iframeElement.findIframeElement());
|
||||
//存储窗体切换记录
|
||||
iframeElementList.add(iframeElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于向上切换指定数量的窗体,若传入的数量大于当前窗体的数量,则将窗体切换至顶层;若传入的数量小于
|
||||
* 等于0,则不进行切换
|
||||
* @param count 需要向上切换窗体的数量
|
||||
*/
|
||||
public void switchParentIframe(int count) {
|
||||
//判断count是否小于等于0,若小于等于0,则不进行切换
|
||||
if (count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//判断count是否大于iframeElementList中所有元素的个数,若大于,则切回至顶层
|
||||
if (count > iframeElementList.size()) {
|
||||
switchRootIframe();
|
||||
return;
|
||||
}
|
||||
|
||||
//循环,对窗体进行切换
|
||||
for (int i = 0; i < count; i++) {
|
||||
//向上切换窗体
|
||||
driver.switchTo().parentFrame();
|
||||
//移除iframeElementList中最后一个元素
|
||||
iframeElementList.remove(iframeElementList.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据By对象集合,查找有效的By对象,并根据有效的By对象,查找相应的元素集合
|
||||
*/
|
||||
public void findElemen() {
|
||||
//遍历By集合,查找有效的By对象,若所有的By对象均无法查到页面元素,则直接抛出超时异常
|
||||
for (int i = 0; i < byList.size(); i++) {
|
||||
//查找元素,若抛出异常,则移除该元素,保证有效的By对象在第一个元素上
|
||||
try {
|
||||
if (isExistElement(byList.get(i))) {
|
||||
break;
|
||||
} else {
|
||||
byList.remove(i);
|
||||
i--;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
byList.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
//若byList被清空,则抛出查找超时的异常
|
||||
if (byList.size() == 0) {
|
||||
throw new TimeoutException("页面无法查找到相应的元素,“" + name + "”元素无有效的By对象");
|
||||
}
|
||||
|
||||
//根据正确的By对象,通过Webdriver,查找到WebElement对象,存储
|
||||
//由于在遍历byList时,无效的By对象被剔除,查找到By对象时会返回,故此时可直接使用第一个元素为有效的By对象
|
||||
switch (elementType) {
|
||||
case COMMON_ELEMENT:
|
||||
case DATA_LIST_ELEMENT:
|
||||
case SELECT_DATAS_ELEMENT:
|
||||
element = driver.findElements(byList.get(0)).get(elementIndex);
|
||||
break;
|
||||
case SELECT_OPTION_ELEMENT:
|
||||
element = new Select(driver.findElement(byList.get(0))).getOptions().get(elementIndex);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected value: " + elementType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于自动切换元素所在窗体
|
||||
*/
|
||||
private void autoSwitchIframe() {
|
||||
//获取元素所在的所有窗体,并存储
|
||||
ArrayList<Element> iframeList = getAllIframe();
|
||||
|
||||
//判断iframeList中是否存在元素,若不存在,则切回顶层后结束运行
|
||||
if (iframeList.isEmpty()) {
|
||||
switchRootIframe();
|
||||
return;
|
||||
}
|
||||
|
||||
//判断iframeElementList是否为空,或iframeList的第一个元素是否存在于iframeElementList中,若不存在,则切回到顶层,并根据iframeList切换窗体
|
||||
if (iframeElementList.size() == 0 || !iframeElementList.contains(iframeList.get(0))) {
|
||||
switchRootIframe();
|
||||
iframeList.forEach(iframeElement -> {
|
||||
switchIframe(iframeElement);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//判断iframeElementList中的最后一个元素是否与iframeList中的最后一个元素一致,若一致,则无需切换
|
||||
if (iframeElementList.get(iframeElementList.size() - 1).equals(iframeList.get(iframeList.size() - 1))) {
|
||||
return;
|
||||
}
|
||||
|
||||
//遍历iframeList,查看iframeList中的窗体元素是否存在于iframeElementList中
|
||||
int index = 0;
|
||||
for (; index < iframeList.size(); index++) {
|
||||
//若当前遍历的元素不存在于iframeElementList中,则结束循环
|
||||
if (!iframeElementList.contains(iframeList.get(index))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//计算需要向上切换窗体的个数
|
||||
//当窗体不存在于iframeElementList中时,其index以比存在的窗体下标大1位,故
|
||||
//index可直接用于计算需要切换窗体的个数
|
||||
switchParentIframe(iframeElementList.size() - index);
|
||||
|
||||
//切换到相应的父层后,再根据iframeList剩余的元素进行切换
|
||||
for (; index < iframeList.size(); index++) {
|
||||
switchIframe(iframeList.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回窗体{@link WebElement}元素
|
||||
* @return 窗体{@link WebElement}元素
|
||||
*/
|
||||
private WebElement findIframeElement() {
|
||||
//若elementList为null或其内无元素,则对元素进行一次查找
|
||||
if (element == null) {
|
||||
findElemen();
|
||||
}
|
||||
|
||||
//返回相应的内容
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断根据传入的{@link By}对象,判断是否能查找到元素
|
||||
* @param by {@link By}对象
|
||||
* @return 是否查找到元素
|
||||
*/
|
||||
boolean isExistElement(By by) {
|
||||
//当查找到元素时,则返回true,若查不到元素,则会抛出异常,故返回false
|
||||
return new WebDriverWait(driver, waitTime, 200).
|
||||
until((driver) -> {
|
||||
WebElement element = driver.findElement(by);
|
||||
return element != null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Element other = (Element) obj;
|
||||
if (element == null) {
|
||||
if (other.element != null)
|
||||
return false;
|
||||
} else if (!element.equals(other.element))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package pres.auxiliary.work.selenium.element.copy;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>EelementType.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 用于标记当前传入的元素是以何种方式进行获取
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年5月22日上午7:57:32</p>
|
||||
* <p><b>修改时间:</b>2020年5月22日上午7:57:32</p>
|
||||
* @author
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public enum ElementType {
|
||||
/**
|
||||
* 指向普通类型元素
|
||||
*/
|
||||
COMMON_ELEMENT,
|
||||
/**
|
||||
* 指向数据列表类型元素
|
||||
*/
|
||||
DATA_LIST_ELEMENT,
|
||||
/**
|
||||
* 指向标准下拉框选择类型元素
|
||||
*/
|
||||
SELECT_OPTION_ELEMENT,
|
||||
/**
|
||||
* 指向列表型下拉框选择类型元素
|
||||
*/
|
||||
SELECT_DATAS_ELEMENT;
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package pres.auxiliary.work.selenium.element.copy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
import pres.auxiliary.work.selenium.element.copy.AbstractBy.ElementInformation;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>ListElement.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 提供获取列表类型元素时的基本方法
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年5月22日上午7:54:55</p>
|
||||
* <p><b>修改时间:</b>2020年5月22日上午7:54:55</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class ListBy extends AbstractBy {
|
||||
/**
|
||||
* 用于存储获取到的列表一列元素,key为列表名称,value为列表元素
|
||||
*/
|
||||
LinkedHashMap<ElementInformation, List<Element>> elementMap = new LinkedHashMap<>(16);
|
||||
|
||||
/**
|
||||
* 通过浏览器对象{@link AbstractBrower}进行构造
|
||||
* @param brower {@link AbstractBrower}对象
|
||||
*/
|
||||
public ListBy(AbstractBrower brower) {
|
||||
super(brower);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回列表名称对应的元素个数,若该列未被获取,则返回-1
|
||||
* @param name 被获取的列名称
|
||||
* @return 列名对应列的元素个数
|
||||
*/
|
||||
public int getSize(String name) {
|
||||
ElementInformation element = nameToElementInformation(name);
|
||||
if (element != null) {
|
||||
return elementMap.get(element).size();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回所有列的名称
|
||||
* @return 所有列的名称
|
||||
*/
|
||||
public ArrayList<String> getNames() {
|
||||
ArrayList<String> nameList = new ArrayList<>();
|
||||
elementMap.forEach((key, value) -> {
|
||||
nameList.add(key.name);
|
||||
});
|
||||
|
||||
return nameList;
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(ElementInformation elementInformation) {
|
||||
//判断传入的元素是否在xml文件中,若存在再判断是否自动切换窗体,若需要,则获取元素的所有父窗体并进行切换
|
||||
if (xml != null && xml.isElement(elementInformation.name) && isAutoSwitchIframe) {
|
||||
switchFrame(getParentFrameName(elementInformation.name));
|
||||
}
|
||||
|
||||
List<Element> elementList = new ArrayList<Element>();
|
||||
//获取元素
|
||||
By by = recognitionElement(elementInformation);
|
||||
int size = driver.findElements(by).size();
|
||||
//构造Element对象
|
||||
for (int i = 0; i < size; i++) {
|
||||
elementList.add(new Element(driver, ElementType.DATA_LIST_ELEMENT, by, elementInformation.name, i));
|
||||
}
|
||||
//elementList = driver.findElements(recognitionElement(elementInformation));
|
||||
//添加元素
|
||||
elementMap.put(elementInformation, elementList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于清除或移除指定的列及列中的元素,当参数传入false时,则只清理列表中存储的元素,不移除
|
||||
* 整个列,若传入true时,则直接移除整个列。若列名称对应的列未被获取,则返回null
|
||||
* @param name 已被获取的元素列名称
|
||||
* @param isRemove 是否需要将该列移除
|
||||
* @return 被移除列中存储的所有元素
|
||||
*/
|
||||
public List<Element> clearColumn(String name, boolean isRemove) {
|
||||
ElementInformation element = nameToElementInformation(name);
|
||||
//若元素不存在,则直接返回null
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//用于存储被移除的元素
|
||||
List<Element> elementList = elementMap.get(element);
|
||||
//判断元素是否需要被完全移除
|
||||
if (isRemove) {
|
||||
//若元素需要被完全移除,则直接移除元素
|
||||
elementMap.remove(element);
|
||||
//由于元素被移除,若该列存在元素个数统计,则同样将该元素移除
|
||||
/*
|
||||
if (elementSizeMap.containsKey(name)) {
|
||||
elementSizeMap.remove(name);
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
//若元素无需移除,则将元素存储的列表内容清空
|
||||
elementMap.get(element).clear();
|
||||
}
|
||||
|
||||
return elementList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void againGetElement() {
|
||||
// 读取elements中的元素
|
||||
elementMap.forEach((key, value) -> {
|
||||
// 清空元素中的内容
|
||||
clearColumn(key.name, false);
|
||||
// 对页面内容重新进行获取
|
||||
add(key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据元素名称反推元素信息类对象,用于根据列名称查找数据以及判断列是否存在,若列名不存在,则返回null
|
||||
* @return ElementInformation对象
|
||||
*/
|
||||
ElementInformation nameToElementInformation(String name) {
|
||||
//遍历elementMap,若查找与name一致的名称,则结束循环并返回相应的ElementInformation对象
|
||||
for (ElementInformation element : elementMap.keySet()) {
|
||||
if (element.name.equals(name)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于根据列名称,查找到相应的列,并返回与传入下标对应的元素。下标支持从后向前获取,传入的下标
|
||||
* 与元素实际所在位置一致,当传入0时,则表示随机获取一个元素,如:<br>
|
||||
* {@code getWebElement("姓名", 1)}表示获取名称为“姓名”的列中的第1个元素<br>
|
||||
* {@code getWebElement("姓名", 0)}表示获取名称为“姓名”的列中在长度范围内随机一个元素<br>
|
||||
* {@code getWebElement("//*[@id='name']", -1)}表示获取“//*[@id='name']”对应列中的倒数第1个元素<br>
|
||||
*
|
||||
* @param name 列名称
|
||||
* @param index 元素下标(即列表中对应的某一个元素)
|
||||
* @return 对应列指定的元素
|
||||
* @throws NoSuchElementException 当未对name列进行获取数据或index的绝对值大于列表最大值时抛出的异常
|
||||
*/
|
||||
public Element getElement(String name, int index) {
|
||||
//获取元素信息,并判断元素是否存在,不存在则抛出异常
|
||||
ElementInformation element = nameToElementInformation(name);
|
||||
if (element == null) {
|
||||
throw new NoSuchElementException("不存在的定位方式:" + name);
|
||||
}
|
||||
|
||||
// 转义下标
|
||||
index = getIndex(elementMap.get(element).size(), index, true);
|
||||
|
||||
// 转义下标后,返回对应的元素
|
||||
return elementMap.get(element).get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于根据列名称,获取该列下所有的元素
|
||||
*
|
||||
* @param name 列名称
|
||||
* @return 对应列元素
|
||||
* @throws NoSuchElementException 当未对name列进行获取数据时抛出的异常
|
||||
*/
|
||||
public List<Element> getAllElement(String name) {
|
||||
//获取元素信息,并判断元素是否存在,不存在则抛出异常
|
||||
ElementInformation element = nameToElementInformation(name);
|
||||
if (element == null) {
|
||||
throw new NoSuchElementException("不存在的定位方式:" + name);
|
||||
}
|
||||
|
||||
return elementMap.get(element);
|
||||
}
|
||||
}
|
|
@ -27,8 +27,6 @@ import org.dom4j.DocumentException;
|
|||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,10 +6,6 @@ import java.io.IOException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.exception.UndefinedDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Log.java</p>
|
||||
* <p><b>用途:</b>用于在txt文件中生成自动化测试相关的日志,亦可指定输出的内容</p>
|
||||
|
|
|
@ -10,7 +10,6 @@ import javax.imageio.ImageIO;
|
|||
import net.sourceforge.tess4j.ITesseract;
|
||||
import net.sourceforge.tess4j.Tesseract;
|
||||
import net.sourceforge.tess4j.TesseractException;
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
|
@ -11,10 +11,6 @@ import org.openqa.selenium.TakesScreenshot;
|
|||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebDriverException;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.exception.UndefinedDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* 该类用于在使用selenium进行自动化测试中进行截图的工具。使用该类时可以指定截图保存的位置以及
|
||||
* 截图的名称,若不设置,则默认路径为C:\\AutoTest\\Screenshot\\,默认文件名称为Image。
|
||||
|
@ -213,35 +209,6 @@ public class Screenshot {
|
|||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于创建截图并保存到相应的路径下,通过指定的截图文件名称和类中存储的WebDriver对象、截图保存路径来创建截图,
|
||||
* 该方法可先按照控件名称查找页面是否存在该控件,存在则截图,若不存在,则返回null
|
||||
*
|
||||
* @param event 事件类(Event)对象
|
||||
* @param controlName 控件名称
|
||||
* @param imageName 指定的截图文件名
|
||||
* @return
|
||||
* @throws IOException
|
||||
* 文件流状态不正确时抛出的异常
|
||||
* @throws WebDriverException
|
||||
* WebDriver引用错误时抛出的异常
|
||||
* @throws NullPointerException
|
||||
* WebDriver为空时抛出的异常
|
||||
* @throws UndefinedDirectoryException
|
||||
* 截图保存路径或截图名称为指定时抛出的异常
|
||||
* @see #creatImage(String)
|
||||
*/
|
||||
public File creatImage(Event event, String controlName, String imageName) throws WebDriverException, IOException {
|
||||
//判断控件名对应的控件是否存在,存在后则截图,否则返回null
|
||||
if ( event.getJudgeEvent().judgeControl(controlName).getBooleanValue() ) {
|
||||
return null;
|
||||
}
|
||||
// 将名称放入属性中
|
||||
setImageName(imageName);
|
||||
// 调用无参方法
|
||||
return saveScreenshot();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于保存并转移截图
|
||||
*
|
||||
|
|
|
@ -1,576 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.xml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>CreateXML.java</p>
|
||||
* <p><b>用途:</b>用于通过指定样式的txt文件,来创建自动化测试所需要的xml文件</p>
|
||||
* <p><b>编码时间:</b>2019年6月1日上午11:41:02</p>
|
||||
* <p><b>修改时间:</b>2019年6月1日上午11:41:02</p>
|
||||
* @author 彭宇琦
|
||||
*
|
||||
*/
|
||||
public class CreateXml {
|
||||
// 用于设置到xml文件存放的路径
|
||||
private static StringBuilder xmlPath = new StringBuilder(
|
||||
"C:\\AutoTest\\Xml\\");
|
||||
private static StringBuilder xmlName = new StringBuilder("");
|
||||
// 用于存储用户选择的定位方式标签
|
||||
private static StringBuilder mode = new StringBuilder("");
|
||||
|
||||
// 定义字段
|
||||
/** 添加xpath标签 */
|
||||
public static final short XPATH = 0;
|
||||
/** 添加css标签 */
|
||||
public static final short CSS = 1;
|
||||
/** 添加id标签 */
|
||||
public static final short ID = 2;
|
||||
/** 添加linktext标签 */
|
||||
public static final short LINKTEXT = 3;
|
||||
/** 添加name标签 */
|
||||
public static final short NAME = 4;
|
||||
/** 添加tagname标签 */
|
||||
public static final short TAGNAME = 5;
|
||||
/** 添加classname标签 */
|
||||
public static final short CLASSNAME = 6;
|
||||
/** 添加default(默认)标签 */
|
||||
public static final short DEFAULT = 7;
|
||||
|
||||
|
||||
/**
|
||||
* 该方法用于返回xml文件的名称(不带后缀)
|
||||
*
|
||||
* @return xml文件的名称
|
||||
*/
|
||||
public static String getXmlName() {
|
||||
return xmlName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于设置xml文件的名称,传入的名称不需要添加后缀,不能为中文
|
||||
*
|
||||
* @param xmlName
|
||||
* xml文件的名称
|
||||
*/
|
||||
public static void setXmlName(String xmlName) {
|
||||
// 判断传入的测试结果文件名称是否符合windows下的命名规则,若不符合,则抛出IncorrectDirectoryException异常
|
||||
if (!MakeDirectory.isFileName(xmlName)) {
|
||||
throw new IncorrectDirectoryException("不合理的文件名称,文件名称:" + xmlName);
|
||||
}
|
||||
|
||||
// 通过判断后,则清空xmlName存储的信息并将新的文件名称放入xmlName种属性中
|
||||
CreateXml.xmlName.delete(0, CreateXml.xmlName.length());
|
||||
CreateXml.xmlName.append(xmlName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回xml文件存放的位置
|
||||
*
|
||||
* @return xml文件存放的位置
|
||||
*/
|
||||
public static String getXmlPath() {
|
||||
return xmlPath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于重新设置xml文件存放的路径,并将Document对象指向新的XML文件
|
||||
*
|
||||
* @param xmlPath
|
||||
* xml的存放路径
|
||||
*/
|
||||
public static void setXmlPath(String xmlPath) {
|
||||
// 将传入的参数进行格式化
|
||||
StringBuilder sb = new StringBuilder(xmlPath);
|
||||
sb = MakeDirectory.formatPath(sb);
|
||||
|
||||
// 判断格式化后的文件路径格式是否符合windonws下文件路径的命名规则,不符合则抛出异常
|
||||
if (!MakeDirectory.isPath(sb.toString())) {
|
||||
System.out.println(sb.toString());
|
||||
throw new IncorrectDirectoryException("不合理的文件夹路径,文件路径:"
|
||||
+ sb.toString());
|
||||
}
|
||||
|
||||
// 将文件路径设置入属性中
|
||||
CreateXml.xmlPath = sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回使用的定位标签的情况,
|
||||
*
|
||||
* @return 正在使用的定位标签
|
||||
*/
|
||||
public static String getMode() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("mode [ ");
|
||||
|
||||
// 判断mode包含的标签
|
||||
if (mode.indexOf("0") > -1) {
|
||||
sb.append("xpath, ");
|
||||
}
|
||||
if (mode.indexOf("1") > -1) {
|
||||
sb.append("css, ");
|
||||
}
|
||||
if (mode.indexOf("2") > -1) {
|
||||
sb.append("id, ");
|
||||
}
|
||||
if (mode.indexOf("3") > -1) {
|
||||
sb.append("linktext, ");
|
||||
}
|
||||
if (mode.indexOf("4") > -1) {
|
||||
sb.append("name, ");
|
||||
}
|
||||
if (mode.indexOf("5") > -1) {
|
||||
sb.append("tagname, ");
|
||||
}
|
||||
if (mode.indexOf("6") > -1) {
|
||||
sb.append("classname, ");
|
||||
}
|
||||
|
||||
// 删除多余的逗号
|
||||
sb.delete(sb.lastIndexOf(","), sb.lastIndexOf(",") + 1);
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于设置需要使用的定位标签,可传入多个参数,若该标签的定位方式已存在,则不重复添加
|
||||
*
|
||||
* @param modes
|
||||
* 传入定位方式组
|
||||
*/
|
||||
public static void setMode(int... modes) {
|
||||
for (int mode : modes) {
|
||||
// 判断mode中是否已经存在定位模型,不存在则添加该模型
|
||||
if (CreateXml.mode.indexOf(String.valueOf(mode)) < 0) {
|
||||
CreateXml.mode.append(String.valueOf(mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过存储的xml文件名创建一个空的xml文件,相当于导出一个模版
|
||||
*
|
||||
* @throws XmlFileNameIsNullException
|
||||
* 当xml文件名为空时抛出
|
||||
* @throws RepeatedXmlFileNameException
|
||||
* 当文件夹中存在与定义的xml文件名同名时抛出(运行时异常)
|
||||
*
|
||||
* @see #create(String...)
|
||||
* @see #create(List)
|
||||
* @see #create(String, List)
|
||||
*/
|
||||
public static void create() throws XmlFileNameIsNullException {
|
||||
create("");
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过存储的xml文件名称创建一个已定义元素名称的xml文件, 传入的名称个数即为创建xml文件内元素的个数
|
||||
*
|
||||
* @param names
|
||||
* 传入的元素名称组
|
||||
* @throws XmlFileNameIsNullException
|
||||
* 当xml文件名为空时抛出
|
||||
* @throws RepeatedXmlFileNameException
|
||||
* 当文件夹中存在与定义的xml文件名同名时抛出(运行时异常)
|
||||
* @see #create()
|
||||
* @see #create(List)
|
||||
* @see #create(String, List)
|
||||
*/
|
||||
public static void create(String... names)
|
||||
throws XmlFileNameIsNullException {
|
||||
create(Arrays.asList(names));
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过传入的xml文件名称创建一个已定义元素名称的xml文件, 传入的数组中存储的名称个数即为创建xml文件内元素的个数
|
||||
*
|
||||
* @param xmlName
|
||||
* 定义的xml文件名称
|
||||
* @param names
|
||||
* 传入的元素名称组
|
||||
* @throws XmlFileNameIsNullException
|
||||
* 当xml文件名为空时抛出
|
||||
* @throws RepeatedXmlFileNameException
|
||||
* 当文件夹中存在与定义的xml文件名同名时抛出(运行时异常)
|
||||
* @see #create()
|
||||
* @see #create(String...)
|
||||
* @see #create(List)
|
||||
*/
|
||||
public static void create(String xmlName, List<String> names)
|
||||
throws XmlFileNameIsNullException {
|
||||
setXmlName(xmlName);
|
||||
create(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法通过存储的xml文件名称创建一个已定义元素名称的xml文件, 传入的数组中存储的名称个数即为创建xml文件内元素的个数
|
||||
*
|
||||
* @param names
|
||||
* 传入的元素名称组
|
||||
* @throws XmlFileNameIsNullException
|
||||
* 当xml文件名为空时抛出
|
||||
* @throws RepeatedXmlFileNameException
|
||||
* 当文件夹中存在与定义的xml文件名同名时抛出(运行时异常)
|
||||
* @see #create()
|
||||
* @see #create(String...)
|
||||
* @see #create(String, List)
|
||||
*/
|
||||
public static void create(List<String> texts)
|
||||
throws XmlFileNameIsNullException {
|
||||
// 判断xml文件的名称是否为空,若为空,则抛出异常
|
||||
if ("".equals(xmlName.toString())) {
|
||||
throw new XmlFileNameIsNullException("xml文件名为空");
|
||||
}
|
||||
|
||||
// 创建存放xml的文件夹
|
||||
File xmlfile = new File(xmlPath.toString());
|
||||
xmlfile.mkdirs();
|
||||
// 将File对象定位到xml文件上
|
||||
xmlfile = new File(xmlfile, (xmlName.toString() + ".xml"));
|
||||
if (xmlfile.exists()) {
|
||||
throw new RepeatedXmlFileNameException("存在的文件名:"
|
||||
+ (xmlName.toString() + ".xml"));
|
||||
}
|
||||
|
||||
//创建空的xml文件
|
||||
Document dom = DocumentHelper.createDocument();
|
||||
|
||||
//设置根元素,并设置根元素的属性
|
||||
dom.setRootElement(dom.addElement("project"));
|
||||
dom.getRootElement().addAttribute("name", xmlName.toString());
|
||||
|
||||
//插入控件元素
|
||||
for (String text : texts) {
|
||||
//创建元素
|
||||
Element e = dom.getRootElement().addElement("element");
|
||||
|
||||
String name = "";
|
||||
String value = "";
|
||||
short valueMode = -1;
|
||||
//判断传入的信息中是否包含分隔符(空格),包含则表示存在录入的数据,则直接写入到xml文件中
|
||||
if ( text.split(" ").length > 1 ) {
|
||||
name = text.split(" ")[0];
|
||||
//value = text.split(" ")[1]; 由于css路径是存在空格的,故不能按照切分的方法存入,应按照截取的方法,从第一个空格的下一位开始截取
|
||||
value = text.substring(text.indexOf(" ") + 1);
|
||||
//判断传入结果的模型
|
||||
valueMode = judgeValue(value);
|
||||
} else {
|
||||
name = text;
|
||||
}
|
||||
|
||||
//设置元素的name属性
|
||||
e.addAttribute("name", name);
|
||||
|
||||
//创建定位方式元素
|
||||
// 定义空mode的开关,当mode为空时则开关打开,并在mode中添加所有的定位标签,最后,若该开关为开启状态,则清空mode中所有的内容
|
||||
boolean modeIsEmpty = false;
|
||||
// 判断mode中是否为空,为空则将开关打开,并想mode中添加所有标签的定位方式
|
||||
if ("".equals(mode.toString())) {
|
||||
modeIsEmpty = true;
|
||||
mode.append(String.valueOf(XPATH));
|
||||
mode.append(String.valueOf(CSS));
|
||||
mode.append(String.valueOf(ID));
|
||||
mode.append(String.valueOf(LINKTEXT));
|
||||
mode.append(String.valueOf(NAME));
|
||||
mode.append(String.valueOf(TAGNAME));
|
||||
mode.append(String.valueOf(CLASSNAME));
|
||||
}
|
||||
|
||||
// 判断mode包含的标签
|
||||
if (mode.indexOf(String.valueOf(XPATH)) > -1 || valueMode == XPATH) {
|
||||
//添加节点
|
||||
Element childElement = e.addElement("xpath");
|
||||
childElement.addAttribute("is_use", "true");
|
||||
//添加value中的内容(若内容为空也不会将其添加到xml文件中,故此处可以直接这样写)
|
||||
if (valueMode == XPATH) {
|
||||
childElement.addText(value);
|
||||
//清空value中的内容,避免出现后面的标签也存入信息
|
||||
value = "";
|
||||
}
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(CSS)) > -1 || valueMode == CSS) {
|
||||
//添加节点
|
||||
Element childElement = e.addElement("css");
|
||||
childElement.addAttribute("is_use", "true");
|
||||
//添加value中的内容(若内容为空也不会将其添加到xml文件中,故此处可以直接这样写)
|
||||
if (valueMode == CSS) {
|
||||
childElement.addText(value);
|
||||
//清空value中的内容,避免出现后面的标签也存入信息
|
||||
value = "";
|
||||
}
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(ID)) > -1) {
|
||||
e.addElement("id").addAttribute("is_use", "true");
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(LINKTEXT)) > -1) {
|
||||
e.addElement("linktext").addAttribute("is_use", "true");
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(NAME)) > -1) {
|
||||
e.addElement("name").addAttribute("is_use", "true");
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(TAGNAME)) > -1) {
|
||||
e.addElement("tagname").addAttribute("is_use", "true");
|
||||
}
|
||||
if (mode.indexOf(String.valueOf(CLASSNAME)) > -1) {
|
||||
e.addElement("classname").addAttribute("is_use", "true");
|
||||
}
|
||||
//如果存在模型值,但系统识别为非xpath和css时,则添加一个temp标签,对模型值进行存储
|
||||
if ( valueMode == DEFAULT ) {
|
||||
//添加注释
|
||||
e.addComment("当前节点作为临时存储节点,该节点在自动化测试中不被读取,请将节点的值放入到相应的标签中");
|
||||
//添加节点
|
||||
Element childElement = e.addElement("temp");
|
||||
childElement.addAttribute("is_use", "false");
|
||||
//存储模型值
|
||||
childElement.addText(value);
|
||||
}
|
||||
|
||||
// 判断modeIsEmpty开关是否开启,若开启,则清空mode中的内容
|
||||
if (modeIsEmpty) {
|
||||
mode.delete(0, mode.length());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// 用于存储xml文件的内容,并添加头文件
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// 添加头标签
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"GBK\"?>\r\n");
|
||||
// 添加dtd文件
|
||||
// sb.append("<!DOCTYPE project SYSTEM \"ElementDTD.dtd\">\r\n");
|
||||
// 添加根标签
|
||||
sb.append("<project name=\"" + xmlName.toString() + "\">\r\n");
|
||||
|
||||
// 添加已有名称的标签
|
||||
for (String name : names) {
|
||||
sb.append(element(name));
|
||||
sb.append("\r\n");
|
||||
}
|
||||
|
||||
sb.append("</project>\r\n");
|
||||
|
||||
// 创建写入流
|
||||
try {
|
||||
FileWriter fw = new FileWriter(xmlfile);
|
||||
fw.write(sb.toString());
|
||||
fw.flush();
|
||||
fw.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
|
||||
// 使用dom4j的漂亮格式
|
||||
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
// 设置xml文件的编码方式
|
||||
format.setEncoding("GBK");
|
||||
//关闭自闭和标签,若不设置此开关,则当元素无内容时其标签会被写为半闭合标签,但我希望标签成对出现
|
||||
format.setExpandEmptyElements(true);
|
||||
|
||||
// 写入xml
|
||||
XMLWriter xmlWriter = null;
|
||||
try {
|
||||
xmlWriter = new XMLWriter(new FileOutputStream(xmlfile),
|
||||
format);
|
||||
xmlWriter.write(dom);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
xmlWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// createDTD();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向文件中读取控件名称并在指定的路径下创建带控件名称的xml文件,通过该方法创建的xml文件名称为读取的文件名称<br/>
|
||||
* 注意,使用该方法时,除了后缀名前可以带“.”外 ,文件名称中不能再出现该符号,否则方法可能会报错
|
||||
*
|
||||
* @param files
|
||||
* 指定的文件,可传入多个
|
||||
* @throws XmlFileNameIsNullException
|
||||
* 当xml文件名为空时抛出
|
||||
* @throws RepeatedXmlFileNameException
|
||||
* 当文件夹中存在与定义的xml文件名同名时抛出(运行时异常)
|
||||
*/
|
||||
public static void create(File... files) throws XmlFileNameIsNullException {
|
||||
// 用于存储从文件中获取到的元素名称
|
||||
List<String> l = new ArrayList<>();
|
||||
|
||||
// 循环,读取传入的文件
|
||||
for (File f : files) {
|
||||
// 判断该文件是否为文件夹,若为文件夹则继续循环
|
||||
if (f.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据符号“.”对获取的文件名称进行分割,使其在xml文件中不再带后缀
|
||||
setXmlName(f.getName().split("\\.")[0]);
|
||||
// 封装高效缓冲文件流
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader(f));
|
||||
// 循环,将读取到的元素名称存储l中,结束条件为,若l中最后一个元素为空,则表示上一次未读取到内容,测试跳出循环
|
||||
String s = br.readLine();
|
||||
while (s != null) {
|
||||
// 直接读取一行文本,并将其存入l中
|
||||
l.add(s);
|
||||
s = br.readLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 调用类中的方法,将存储的控件名称转换成xml,若文件名重复,则跳过
|
||||
try {
|
||||
create(l);
|
||||
} catch (RepeatedXmlFileNameException e) {
|
||||
//TODO 控制台输出跳过创建的信息
|
||||
System.out.println(f.getName().split("\\.")[0] + ".xml文件已存在,跳过");
|
||||
}
|
||||
|
||||
// 清空l中的所有内容,重新进行循环
|
||||
l.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于判断传入的值,但目前只能判断xpath和css,若非这两种,则返回default
|
||||
*/
|
||||
private static short judgeValue(String value) {
|
||||
// 如果抛出元素名称查找不到的的异常,则对应匹配xpath和css两种定位方式
|
||||
// 匹配xpath定位,判定方法,判断text的第一个字符是否是“/”
|
||||
if (value.indexOf("/") == 0) {
|
||||
return XPATH;
|
||||
} else if (value.indexOf("html") == 0) {
|
||||
// 匹配css,判断方法:判断text的前四个字符是否是“html”
|
||||
return CSS;
|
||||
} else {
|
||||
return DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于创建元素标签以及元素下的定位方式标签
|
||||
*
|
||||
* @param name
|
||||
* element标签的name属性值
|
||||
* @return 添加标签后的StringBuilder对象
|
||||
*/
|
||||
/*
|
||||
private static StringBuilder element(String name) {
|
||||
// 定义空mode的开关,当mode为空时则开关打开,并在mode中添加所有的定位标签,最后,若该开关为开启状态,则清空mode中所有的内容
|
||||
boolean modeIsEmpty = false;
|
||||
// 判断mode中是否为空,为空则将开关打开,并想mode中添加所有标签的定位方式
|
||||
if (mode.toString().equals("")) {
|
||||
modeIsEmpty = true;
|
||||
mode.append(String.valueOf(XPATH));
|
||||
mode.append(String.valueOf(CSS));
|
||||
mode.append(String.valueOf(ID));
|
||||
mode.append(String.valueOf(LINKTEXT));
|
||||
mode.append(String.valueOf(NAME));
|
||||
mode.append(String.valueOf(TAGNAME));
|
||||
mode.append(String.valueOf(CLASSNAME));
|
||||
}
|
||||
|
||||
// 用于拼接xml文件内容
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// 添加element标签
|
||||
sb.append(" <element name=\"" + name + "\">\r\n");
|
||||
// 添加所有的定位方式标签
|
||||
// 判断mode包含的标签
|
||||
if (mode.indexOf("0") > -1) {
|
||||
sb.append(" <xpath is_use=\"true\"></xpath>\r\n");
|
||||
}
|
||||
if (mode.indexOf("1") > -1) {
|
||||
sb.append(" <css is_use=\"true\"></css>\r\n");
|
||||
}
|
||||
if (mode.indexOf("2") > -1) {
|
||||
sb.append(" <id is_use=\"true\"></id>\r\n");
|
||||
}
|
||||
if (mode.indexOf("3") > -1) {
|
||||
sb.append(" <linktext is_use=\"true\"></linktext>\r\n");
|
||||
}
|
||||
if (mode.indexOf("4") > -1) {
|
||||
sb.append(" <name is_use=\"true\"></name>\r\n");
|
||||
}
|
||||
if (mode.indexOf("5") > -1) {
|
||||
sb.append(" <tagname is_use=\"true\"></tagname>\r\n");
|
||||
}
|
||||
if (mode.indexOf("6") > -1) {
|
||||
sb.append(" <classname is_use=\"true\"></classname>\r\n");
|
||||
}
|
||||
sb.append(" </element>\r\n");
|
||||
|
||||
// 判断modeIsEmpty开关是否开启,若开启,则清空mode中的内容
|
||||
if (modeIsEmpty) {
|
||||
mode.delete(0, mode.length());
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 该方法用于配套xml生成的DTD文件,用于限制输入
|
||||
*/
|
||||
/*
|
||||
private static void createDTD() {
|
||||
// 在xml文件存放的目录下创建一个dtd文件
|
||||
File f = new File(xmlPath.toString() + "\\ElementDTD.dtd");
|
||||
// 判断ElementDTD.dtd文件是否存在,存在则不创建文件,返回
|
||||
if (f.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 若不存在,则存储dtd代码,并生成文件
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// 限制project标签下可以有多个element元素
|
||||
sb.append("<!ELEMENT project (element+)>\r\n");
|
||||
// 限制element标签下的定位方式标签可出现一次或零次
|
||||
sb.append("<!ELEMENT element (xpath?,css?,id?,linktext?,name?,tagname?,classname?)>\r\n");
|
||||
// 对于定位方式标签限制没有子标签,数据为字符型数据
|
||||
sb.append("<!ELEMENT xpath (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT css (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT id (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT linktext (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT name (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT tagname (#PCDATA)>\r\n");
|
||||
sb.append("<!ELEMENT classname (#PCDATA)>\r\n");
|
||||
// 限制project中的name属性的值为非必要
|
||||
sb.append("<!ATTLIST project name CDATA #IMPLIED>\r\n");
|
||||
// 限制element中的name属性的值为唯一且必要
|
||||
sb.append("<!ATTLIST element name ID #REQUIRED>\r\n");
|
||||
|
||||
try {
|
||||
FileWriter fw = new FileWriter(f);
|
||||
fw.write(sb.toString());
|
||||
fw.flush();
|
||||
fw.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.xml;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
/**
|
||||
* 该类用于向xml文件中写入页面元素的定位方式
|
||||
* @author 彭宇琦
|
||||
* @version Ver0.7
|
||||
*/
|
||||
public class WriteXml {
|
||||
// 用于设置到xml文件存放的路径
|
||||
private StringBuilder xmlPath;
|
||||
// 用于读取XML文件
|
||||
private Document dom;
|
||||
|
||||
/**
|
||||
* 用于构造对象,并设置xml文件的路径
|
||||
*
|
||||
* @param xmlPath
|
||||
* 代读取的xml文件路径
|
||||
*/
|
||||
public WriteXml(String xmlPath) {
|
||||
setXmlPath(xmlPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于返回xml文件存放的位置
|
||||
*
|
||||
* @return xml文件存放的位置
|
||||
*/
|
||||
public String getXmlPath() {
|
||||
return xmlPath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于重新设置xml文件存放的路径,并将Document对象指向新的XML文件
|
||||
*
|
||||
* @param xmlPath
|
||||
* xml的存放路径
|
||||
*/
|
||||
public void setXmlPath(String xmlPath) {
|
||||
// 将传入的参数进行格式化
|
||||
StringBuilder sb = new StringBuilder(xmlPath);
|
||||
sb = MakeDirectory.formatPath(sb);
|
||||
|
||||
// 判断格式化后的文件路径格式是否符合windonws下文件路径的命名规则,不符合则抛出异常
|
||||
if (!MakeDirectory.isPath(sb.toString())) {
|
||||
throw new IncorrectDirectoryException("不合理的文件夹路径,文件路径:"
|
||||
+ sb.toString());
|
||||
}
|
||||
|
||||
// 重新构造Document对象,使其指向新的XML文件
|
||||
try {
|
||||
dom = new SAXReader().read(sb.toString());
|
||||
} catch (DocumentException e) {
|
||||
// 若抛出异常,则将异常转换为自定义的IncorrectXMLFileException异常,使其不需要在编译时处理
|
||||
throw new IncorrectXmlPathException("XML文件不正确或XML路径不正确");
|
||||
}
|
||||
|
||||
// 将文件路径设置入属性中
|
||||
this.xmlPath = sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于向xml文件中添加页面元素的定位方式
|
||||
* @param name 页面元素的名称
|
||||
* @param mode 定位的方式
|
||||
* @param value 定位路径
|
||||
* @return
|
||||
*/
|
||||
public boolean writeElement(String name, String mode, String value) {
|
||||
//获取根元素
|
||||
Element e = dom.getRootElement();
|
||||
//在根元素下方添加新元素
|
||||
e.addElement("element").addAttribute("name", name).addText(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ import org.dom4j.DocumentHelper;
|
|||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.work.selenium.datadriven.ListFileRead;
|
||||
import pres.auxiliary.work.testcase.templet.Case;
|
||||
import pres.auxiliary.work.testcase.templet.LabelNotFoundException;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.dom4j.DocumentException;
|
|||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.work.selenium.datadriven.ListFileRead;
|
||||
import pres.auxiliary.work.testcase.templet.LabelNotFoundException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,6 @@ import javax.swing.JTextField;
|
|||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import pres.auxiliary.directory.exception.IncorrectDirectoryException;
|
||||
import pres.auxiliary.work.old.testcase.templet.ZentaoTemplet;
|
||||
|
||||
public class WriteCaseMainFrame extends JFrame {
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.io.File;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import pres.auxiliary.work.selenium.xml.CreateXml;
|
||||
import pres.auxiliary.work.selenium.xml.XmlFileNameIsNullException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class PresetStringTest {
|
||||
@Test
|
||||
public void IdentityCardTest() {
|
||||
System.out.println(PresetString.identityCard());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMobleNumberTest() {
|
||||
System.out.println(PresetString.mobleNumber(MobleNumberType.CHINA_MOBILE));
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ package pres.auxiliary.work.selenium.brower;
|
|||
import java.io.File;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -228,4 +230,70 @@ public class TestChromeBrower {
|
|||
cb.switchWindow(page);
|
||||
cb.closeLabel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasPopuWindowTest() {
|
||||
Page page = new Page("http://test.gxjzgr.caihcloud.com/#/home/index", "桂建通");
|
||||
cb = new ChromeBrower(driverFile, page);
|
||||
|
||||
//不加载图片
|
||||
cb.addConfig(ChromeOptionType.DONOT_LOAD_IMAGE);
|
||||
cb.addConfig(ChromeOptionType.SET_WINDOW_MAX_SIZE);
|
||||
|
||||
WebDriver driver = cb.getDriver();
|
||||
System.out.println("是否存在弹窗:" + cb.hasPopuWindow());
|
||||
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
|
||||
System.out.println("是否存在弹窗:" + cb.hasPopuWindow());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchPopuWindowTest_singlePage() {
|
||||
Page page = new Page("http://test.gxjzgr.caihcloud.com/#/home/index", "桂建通");
|
||||
cb = new ChromeBrower(driverFile, page);
|
||||
|
||||
//不加载图片
|
||||
cb.addConfig(ChromeOptionType.DONOT_LOAD_IMAGE);
|
||||
cb.addConfig(ChromeOptionType.SET_WINDOW_MAX_SIZE);
|
||||
|
||||
WebDriver driver = cb.getDriver();
|
||||
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
// cb.switchNowPage();
|
||||
|
||||
System.out.println("是否切换至弹窗:" + cb.switchPopuWindow());
|
||||
System.out.println(cb.getNowPage().getPageName());
|
||||
cb.closeLabel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchPopuWindowTest_MuPage() {
|
||||
Page page = new Page("http://test.gxjzgr.caihcloud.com/#/home/index", "桂建通");
|
||||
cb = new ChromeBrower(driverFile, page);
|
||||
|
||||
//不加载图片
|
||||
cb.addConfig(ChromeOptionType.DONOT_LOAD_IMAGE);
|
||||
cb.addConfig(ChromeOptionType.SET_WINDOW_MAX_SIZE);
|
||||
|
||||
WebDriver driver = cb.getDriver();
|
||||
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
driver.findElement(By.xpath("//*[text()='账号注册']")).click();
|
||||
// cb.switchNowPage();
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
try {
|
||||
driver.findElement(By.xpath("//*[@alog-action=\"search11111\"]")).click();
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
System.out.println(i++);
|
||||
} while(cb.switchPopuWindow());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.junit.Before;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import pres.auxiliary.work.selenium.datadriven.DataDriven;
|
||||
import pres.auxiliary.work.selenium.datadriven.DataNotFoundException;
|
||||
|
||||
public class TestDataDriven {
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.testng.annotations.Test;
|
|||
|
||||
import pres.auxiliary.work.selenium.brower.ChromeBrower;
|
||||
import pres.auxiliary.work.selenium.brower.ChromeBrower.ChromeOptionType;
|
||||
import pres.auxiliary.work.selenium.element.copy.CommonBy;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>CommonElementTest.java</p>
|
||||
|
@ -38,11 +39,6 @@ public class CommonByTest {
|
|||
cb.getDriver().quit();
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
public void switchRootFrame() {
|
||||
ce.switchRootFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于测试非xml文件中的传参进行窗体切换与元素的获取
|
||||
*/
|
||||
|
@ -99,7 +95,7 @@ public class CommonByTest {
|
|||
@Test
|
||||
public void getElementTest() {
|
||||
File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml");
|
||||
ce.setXmlFile(xmlFile, false);
|
||||
ce.setXmlFile(xmlFile);
|
||||
System.out.println(ce.getElement("搜索条件", "工资单编号").getWebElement().getAttribute("type"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package pres.auxiliary.work.selenium.element;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.testng.annotations.AfterClass;
|
||||
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;
|
||||
import pres.auxiliary.work.selenium.element.copy.Element;
|
||||
import pres.auxiliary.work.selenium.element.copy.ElementType;
|
||||
|
||||
public class ElementTest {
|
||||
/**
|
||||
* 主窗体元素
|
||||
*/
|
||||
Element mainFrameElement;
|
||||
/**
|
||||
* 工资发放详情窗体元素
|
||||
*/
|
||||
Element payrollFrameElement;
|
||||
/**
|
||||
* 单位名称元素
|
||||
*/
|
||||
Element comNameElement;
|
||||
/**
|
||||
* 专户名称元素
|
||||
*/
|
||||
Element payrollElement;
|
||||
/**
|
||||
* 标题元素
|
||||
*/
|
||||
Element titleElement;
|
||||
|
||||
ChromeBrower cb;
|
||||
|
||||
@BeforeClass
|
||||
public void init() {
|
||||
cb = new ChromeBrower(new File("Resource/BrowersDriver/Chrom/78.0394.70/chromedriver.exe"));
|
||||
cb.addConfig(ChromeOptionType.CONTRAL_OPEN_BROWER, "127.0.0.1:9222");
|
||||
|
||||
ArrayList<By> mainFrameByList = new ArrayList<By>();
|
||||
mainFrameByList.add(By.xpath("//iframe[contains(@src,'/Regulatory/admin/index.jsp')]"));
|
||||
mainFrameElement = new Element(cb, "主窗体元素", ElementType.COMMON_ELEMENT, 0);
|
||||
mainFrameElement.setByList(mainFrameByList);
|
||||
|
||||
|
||||
ArrayList<By> payrollFrameByList = new ArrayList<By>();
|
||||
payrollFrameByList.add(By.xpath("//iframe[contains(@src,'工资单管理')]"));
|
||||
payrollFrameElement = new Element(cb, "工资发放详情窗体元素", ElementType.COMMON_ELEMENT, 0);
|
||||
payrollFrameElement.setByList(payrollFrameByList);
|
||||
payrollFrameElement.setIframeElement(mainFrameElement);
|
||||
|
||||
ArrayList<By> comNameByList = new ArrayList<By>();
|
||||
comNameByList.add(By.xpath("//*[@id='listBox']/li[1]/div[1]/p/span[1]"));
|
||||
comNameElement = new Element(cb, "单位名称元素", ElementType.COMMON_ELEMENT, 0);
|
||||
comNameElement.setByList(comNameByList);
|
||||
comNameElement.setIframeElement(payrollFrameElement);
|
||||
|
||||
ArrayList<By> payrollByList = new ArrayList<By>();
|
||||
payrollByList.add(By.xpath("//*[@class='pay-code']"));
|
||||
payrollElement = new Element(cb, "专户名称元素", ElementType.COMMON_ELEMENT, 0);
|
||||
payrollElement.setByList(payrollByList);
|
||||
payrollElement.setIframeElement(payrollFrameElement);
|
||||
|
||||
ArrayList<By> titleByList = new ArrayList<By>();
|
||||
titleByList.add(By.xpath("//*[@lay-id='工资单管理']"));
|
||||
titleElement = new Element(cb, "标题元素", ElementType.COMMON_ELEMENT, 0);
|
||||
titleElement.setByList(titleByList);
|
||||
titleElement.setIframeElement(mainFrameElement);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void closeDriver() {
|
||||
cb.getDriver().quit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWebElementTest() {
|
||||
System.out.println(comNameElement.getWebElement().getText());
|
||||
System.out.println("----------------------------------------");
|
||||
System.out.println(payrollElement.getWebElement().getText());
|
||||
System.out.println("----------------------------------------");
|
||||
System.out.println(titleElement.getWebElement().getText());
|
||||
System.out.println("----------------------------------------");
|
||||
System.out.println(payrollElement.getWebElement().getText());
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package test.javase;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import pres.auxiliary.work.selenium.xml.CreateXml;
|
||||
import pres.auxiliary.work.selenium.xml.XmlFileNameIsNullException;
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package test.javase;
|
||||
|
||||
import pres.auxiliary.directory.operate.MakeDirectory;
|
||||
|
||||
public class TestMakeDirector {
|
||||
public static void main(String[] args) {
|
||||
// MakeDirectory.createAllFolder();
|
||||
|
|
Loading…
Reference in New Issue