调整包结构,清理报错类,添加列表事件类
This commit is contained in:
parent
a8923f2f99
commit
a0c8c09c63
File diff suppressed because it is too large
Load Diff
|
@ -1,45 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class AutoTestReport extends AbstractReport implements ReportInter {
|
||||
/**
|
||||
* 该构造只用于创建对象
|
||||
*/
|
||||
public AutoTestReport() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 该构造方法用于设置测试报告保存位置
|
||||
*
|
||||
* @param savePath
|
||||
* 测试报告保存位置
|
||||
*/
|
||||
public AutoTestReport(String savePath) {
|
||||
setSavePath(savePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReport(File excel, int testDay, String person,
|
||||
String range) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReport(String name, String version, int testDay, String person, String range, int activeOne,
|
||||
int activeTwo, int activeThree, int activeFour, int one, int two, int three, int four, int noSulveOne,
|
||||
int noSulveTwo, int delayOne, int delayTwo, String accessory) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* @Override public void createReport(File folder, int[] testDay, String[]
|
||||
* person, String[] range) throws IOException { // TODO Auto-generated
|
||||
* method stub
|
||||
*
|
||||
* }
|
||||
*/
|
||||
}
|
|
@ -1,269 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
class BugFilePosition {
|
||||
/**
|
||||
* 设置配置文件存放的位置
|
||||
*/
|
||||
private final static String xml = "ConfigurationFiles/ReportConfigurationFile/TestReportConfiguration.xml";
|
||||
/**
|
||||
* Bug编号
|
||||
*/
|
||||
public static int ID;
|
||||
/**
|
||||
* 所属产品
|
||||
*/
|
||||
public static int PRODUCT;
|
||||
/**
|
||||
* 所属模块
|
||||
*/
|
||||
public static int MODULE;
|
||||
/**
|
||||
* 所属项目
|
||||
*/
|
||||
public static int PROJECT;
|
||||
/**
|
||||
* Bug标题
|
||||
*/
|
||||
public static int TITLE;
|
||||
/**
|
||||
* 严重程度
|
||||
*/
|
||||
public static int SIGNIFICANCE;
|
||||
/**
|
||||
* Bug类型
|
||||
*/
|
||||
public static int TYPE;
|
||||
/**
|
||||
* 步骤
|
||||
*/
|
||||
public static int STEP;
|
||||
/**
|
||||
* 激活次数
|
||||
*/
|
||||
public static int ACTIVE_COUNT;
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
public static int CREATE_PERSON;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
public static int CREATE_TIME;
|
||||
/**
|
||||
* 影响版本
|
||||
*/
|
||||
public static int VERSION;
|
||||
/**
|
||||
* 指派给
|
||||
*/
|
||||
public static int ASSIGN_PERSON;
|
||||
/**
|
||||
* 解决方案
|
||||
*/
|
||||
public static int SOULVE_WAY;
|
||||
|
||||
//通过静态代码块的方式,在未构造类的情况下根据配置文件中的值来初始化其列数
|
||||
static {
|
||||
// 读取配置好的XML文件
|
||||
Document dom = null;
|
||||
try {
|
||||
dom = new SAXReader().read(new File(xml));
|
||||
} catch (DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 获取测试报告中的内容
|
||||
String type = dom.getRootElement().attributeValue("type");
|
||||
|
||||
//判断测试由何处导出,之后初始化其值
|
||||
if ( type.equalsIgnoreCase("Zentao") || type.equalsIgnoreCase("") ) {
|
||||
ID = Zentao.ID.getCell();
|
||||
PRODUCT = Zentao.PRODUCT.getCell();
|
||||
MODULE = Zentao.MODULE.getCell();
|
||||
PROJECT = Zentao.PROJECT.getCell();
|
||||
TITLE = Zentao.TITLE.getCell();
|
||||
SIGNIFICANCE = Zentao.SIGNIFICANCE.getCell();
|
||||
TYPE = Zentao.TYPE.getCell();
|
||||
STEP = Zentao.STEP.getCell();
|
||||
ACTIVE_COUNT = Zentao.ACTIVE_COUNT.getCell();
|
||||
CREATE_PERSON = Zentao.CREATE_PERSON.getCell();
|
||||
CREATE_TIME = Zentao.CREATE_TIME.getCell();
|
||||
VERSION = Zentao.VERSION.getCell();
|
||||
VERSION = Zentao.VERSION.getCell();
|
||||
ASSIGN_PERSON = Zentao.ASSIGN_PERSON.getCell();
|
||||
SOULVE_WAY = Zentao.SOULVE_WAY.getCell();
|
||||
} else if ( type.equalsIgnoreCase("TFS") ) {
|
||||
ID = TFS.ID.getCell();
|
||||
PRODUCT = TFS.PRODUCT.getCell();
|
||||
MODULE = TFS.MODULE.getCell();
|
||||
PROJECT = TFS.PROJECT.getCell();
|
||||
TITLE = TFS.TITLE.getCell();
|
||||
SIGNIFICANCE = TFS.SIGNIFICANCE.getCell();
|
||||
TYPE = TFS.TYPE.getCell();
|
||||
STEP = TFS.STEP.getCell();
|
||||
ACTIVE_COUNT = TFS.ACTIVE_COUNT.getCell();
|
||||
CREATE_PERSON = TFS.CREATE_PERSON.getCell();
|
||||
CREATE_TIME = TFS.CREATE_TIME.getCell();
|
||||
VERSION = TFS.VERSION.getCell();
|
||||
VERSION = TFS.VERSION.getCell();
|
||||
ASSIGN_PERSON = TFS.ASSIGN_PERSON.getCell();
|
||||
SOULVE_WAY = TFS.SOULVE_WAY.getCell();
|
||||
} else {
|
||||
throw new InvalidBugListFileSignException("无效的Bug汇总表文件标识:" + type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于指向禅道导出的BUG汇总表文件中的各个信息
|
||||
*
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
private enum Zentao {
|
||||
/**
|
||||
* Bug编号
|
||||
*/
|
||||
ID(0),
|
||||
/**
|
||||
* 所属产品
|
||||
*/
|
||||
PRODUCT(1),
|
||||
/**
|
||||
* 所属模块
|
||||
*/
|
||||
MODULE(2),
|
||||
/**
|
||||
* 所属项目
|
||||
*/
|
||||
PROJECT(3),
|
||||
/**
|
||||
* Bug标题
|
||||
*/
|
||||
TITLE(6),
|
||||
/**
|
||||
* 严重程度
|
||||
*/
|
||||
SIGNIFICANCE(8),
|
||||
/**
|
||||
* Bug类型
|
||||
*/
|
||||
TYPE(10),
|
||||
/**
|
||||
* 步骤
|
||||
*/
|
||||
STEP(13),
|
||||
/**
|
||||
* 激活次数
|
||||
*/
|
||||
ACTIVE_COUNT(16),
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
CREATE_PERSON(19),
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
CREATE_TIME(20),
|
||||
/**
|
||||
* 影响版本
|
||||
*/
|
||||
VERSION(21),
|
||||
/**
|
||||
* 指派给
|
||||
*/
|
||||
ASSIGN_PERSON(22),
|
||||
/**
|
||||
* 解决方案
|
||||
*/
|
||||
SOULVE_WAY(25);
|
||||
|
||||
private int cell;
|
||||
|
||||
private Zentao(int cell) {
|
||||
this.cell = cell;
|
||||
}
|
||||
|
||||
public int getCell() {
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于指向TFS导出的BUG汇总表文件中的各个信息
|
||||
*
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
private enum TFS {
|
||||
/**
|
||||
* Bug编号
|
||||
*/
|
||||
ID(-1),
|
||||
/**
|
||||
* 所属产品
|
||||
*/
|
||||
PRODUCT(-1),
|
||||
/**
|
||||
* 所属模块
|
||||
*/
|
||||
MODULE(-1),
|
||||
/**
|
||||
* 所属项目
|
||||
*/
|
||||
PROJECT(-1),
|
||||
/**
|
||||
* Bug标题
|
||||
*/
|
||||
TITLE(-1),
|
||||
/**
|
||||
* 严重程度
|
||||
*/
|
||||
SIGNIFICANCE(-1),
|
||||
/**
|
||||
* Bug类型
|
||||
*/
|
||||
TYPE(-1),
|
||||
/**
|
||||
* 步骤
|
||||
*/
|
||||
STEP(-1),
|
||||
/**
|
||||
* 激活次数
|
||||
*/
|
||||
ACTIVE_COUNT(-1),
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
CREATE_PERSON(-1),
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
CREATE_TIME(-1),
|
||||
/**
|
||||
* 影响版本
|
||||
*/
|
||||
VERSION(-1),
|
||||
/**
|
||||
* 指派给
|
||||
*/
|
||||
ASSIGN_PERSON(-1),
|
||||
/**
|
||||
* 解决方案
|
||||
*/
|
||||
SOULVE_WAY(-1);
|
||||
|
||||
private int cell;
|
||||
|
||||
private TFS(int cell) {
|
||||
this.cell = cell;
|
||||
}
|
||||
|
||||
public int getCell() {
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
/**
|
||||
* 在格式不兼容时抛出的异常
|
||||
*
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
public class IncompatibleFileLayoutException extends RuntimeException {
|
||||
|
||||
public IncompatibleFileLayoutException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncompatibleFileLayoutException(String message, Throwable cause,
|
||||
boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncompatibleFileLayoutException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncompatibleFileLayoutException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncompatibleFileLayoutException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
public class IncorrectBugVersionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public IncorrectBugVersionException() {
|
||||
super();
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public IncorrectBugVersionException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
|
||||
super(arg0, arg1, arg2, arg3);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public IncorrectBugVersionException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public IncorrectBugVersionException(String arg0) {
|
||||
super(arg0);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public IncorrectBugVersionException(Throwable arg0) {
|
||||
super(arg0);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
/**
|
||||
* 该异常在XML文件语法出错时抛出的异常
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
public class IncorrectGrammarException extends RuntimeException {
|
||||
|
||||
public IncorrectGrammarException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectGrammarException(String message, Throwable cause,
|
||||
boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectGrammarException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectGrammarException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public IncorrectGrammarException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
public class InvalidBugListFileSignException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidBugListFileSignException() {
|
||||
super();
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public InvalidBugListFileSignException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
|
||||
super(arg0, arg1, arg2, arg3);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public InvalidBugListFileSignException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public InvalidBugListFileSignException(String arg0) {
|
||||
super(arg0);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
public InvalidBugListFileSignException(Throwable arg0) {
|
||||
super(arg0);
|
||||
// TODO 自动生成的构造函数存根
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
/**
|
||||
* 该类用于创建报告文件对象的类型,传入“TestReport”表示测试报告,传入“AutoTestPath”表示自动化测试报告
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class ReportFactory {
|
||||
/**
|
||||
* 该方法用于通过带参构造的方法创建报告类对象
|
||||
*
|
||||
* @param report
|
||||
* 报告的类型
|
||||
* @param savePath
|
||||
* 报告的输出位置
|
||||
* @return 报告类对象
|
||||
*/
|
||||
public static AbstractReport newInstance(String report, String savePath) {
|
||||
if (report.equalsIgnoreCase("TestReport")) {
|
||||
return new TestReport(savePath);
|
||||
} else if (report.equalsIgnoreCase("AutoTestPath")) {
|
||||
return new AutoTestReport(savePath);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于通过无参构造的方法创建报告类对象
|
||||
*
|
||||
* @param report
|
||||
* 报告的类型
|
||||
* @return 报告类对象
|
||||
*/
|
||||
public static AbstractReport newInstance(String report) {
|
||||
if (report.equalsIgnoreCase("TestReport")) {
|
||||
return new TestReport();
|
||||
} else if (report.equalsIgnoreCase("AutoTestPath")) {
|
||||
return new AutoTestReport();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
package pres.auxiliary.report;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 该接口定义了测试报告类应实现的方法
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public interface ReportInter {
|
||||
/**
|
||||
* 该方法用于生成测试报告的参数
|
||||
*
|
||||
* @param name
|
||||
* 项目名称
|
||||
* @param version
|
||||
* 项目版本号
|
||||
* @param testDay
|
||||
* 测试的天数
|
||||
* @param person
|
||||
* 测试人员
|
||||
* @param range
|
||||
* 测试的范围
|
||||
* @param one
|
||||
* 一级Bug的数量
|
||||
* @param two
|
||||
* 二级Bug的数量
|
||||
* @param three
|
||||
* 三级Bug的数量
|
||||
* @param four
|
||||
* 四级Bug的数量
|
||||
* @param noSulveOne
|
||||
* 原版本中未解决的一级Bug的数量
|
||||
* @param noSulveTwo
|
||||
* 原版本中未解决的二级Bug的数量
|
||||
* @param delayOne 原版本中延期解决的一级Bug的数量
|
||||
* @param delayTwo 原版本中延期解决的二级Bug的数量
|
||||
* @param accessory
|
||||
* 附件存放位置
|
||||
* @param activeOne
|
||||
* 激活的一级BUG的数量
|
||||
* @param activeTwo
|
||||
* 激活的二级BUG的数量
|
||||
* @param activeThree
|
||||
* 激活的三级BUG的数量
|
||||
* @param activeFour
|
||||
* 激活的四级BUG的数量
|
||||
* @return 测试报告邮件中正文的内容
|
||||
*
|
||||
* @see #createReport(File, int, String, String)
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract String createReport(String name, String version,
|
||||
int testDay, String person, String range, int activeOne,
|
||||
int activeTwo, int activeThree, int activeFour, int one, int two,
|
||||
int three, int four, int noSulveOne,
|
||||
int noSulveTwo, int delayOne, int delayTwo, String accessory)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* 该方法用于通过读取BUG汇总表中的信息来生成测试报告
|
||||
*
|
||||
* @param excel
|
||||
* BUG汇总表文件
|
||||
* @param testDay
|
||||
* 测试的天数
|
||||
* @param person
|
||||
* 测试人员
|
||||
* @param range
|
||||
* 测试范围
|
||||
* @return 测试报告邮件中正文的内容
|
||||
* @see #createReport(String, String, int, String, String, int, int, int,
|
||||
* int, String)
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract String createReport(File excel, int testDay, String person,
|
||||
String range) throws IOException;
|
||||
|
||||
/**
|
||||
* 该方法用于读取Bug汇总表,其返回的数组存储的信息如下表所示:<br/>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>s[0]:项目名称</td>
|
||||
* <td>s[1]:当前版本</td>
|
||||
* <td>s[2]:1级BUG数量</td>
|
||||
* <td>s[3]:2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[4]:3级BUG数量</td>
|
||||
* <td>s[5]:4级BUG数量</td>
|
||||
* <td>s[6]:激活1级BUG数量</td>
|
||||
* <td>s[7]:激活2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[8]:激活3级BUG数量</td>
|
||||
* <td>s[9]:激活4级BUG数量</td>
|
||||
* <td>s[10]:未解决的1级BUG数量</td>
|
||||
* <td>s[11]:未解决的2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[12]:延期解决1级BUG数量</td>
|
||||
* <td>s[13]:延期解决2级BUG数量</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* @param excel
|
||||
* BUG汇总表
|
||||
* @param testDay
|
||||
* 测试的天数
|
||||
* @return Bug汇总表中提取的信息
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract String[] readFile(File excel, int testDay)
|
||||
throws IOException;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,186 +0,0 @@
|
|||
package pres.auxiliary.report.ui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.WindowConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import org.dom4j.DocumentException;
|
||||
|
||||
/**
|
||||
* FileName: SandMailFrame.java
|
||||
*
|
||||
* 用于给出一个发送邮件确认的弹窗,在该弹窗上可以修改邮件收件人和抄送人
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @Deta 2018年4月27日 下午4:49:26
|
||||
* @version ver1.0
|
||||
*/
|
||||
public class SandMailFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -1048290948430116615L;
|
||||
private JPanel contentPane;
|
||||
protected static JTextArea to;
|
||||
protected static JTextArea cc;
|
||||
protected static JTextArea content;
|
||||
static SandMailFrame frame = new SandMailFrame();
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public SandMailFrame() {
|
||||
setTitle("\u68C0\u67E5\u90AE\u4EF6\u63A5\u6536\u4EBA");
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setBounds(100, 100, 487, 607);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
contentPane.setLayout(null);
|
||||
|
||||
JLabel label = new JLabel("\u6536\u4EF6\u4EBA\uFF1A");
|
||||
label.setBounds(10, 10, 65, 15);
|
||||
contentPane.add(label);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane();
|
||||
scrollPane.setBounds(10, 35, 414, 93);
|
||||
contentPane.add(scrollPane);
|
||||
|
||||
to = new JTextArea();
|
||||
to.setEditable(false);
|
||||
to.setLineWrap(true);
|
||||
scrollPane.setViewportView(to);
|
||||
|
||||
JLabel label_1 = new JLabel("\u6284\u9001\u4EBA\uFF1A");
|
||||
label_1.setBounds(10, 138, 65, 15);
|
||||
contentPane.add(label_1);
|
||||
|
||||
JScrollPane scrollPane_1 = new JScrollPane();
|
||||
scrollPane_1.setBounds(10, 163, 414, 93);
|
||||
contentPane.add(scrollPane_1);
|
||||
|
||||
cc = new JTextArea();
|
||||
cc.setEditable(false);
|
||||
cc.setLineWrap(true);
|
||||
scrollPane_1.setViewportView(cc);
|
||||
|
||||
JButton yes = new JButton("\u786E\u5B9A");
|
||||
yes.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 执行发送邮件的方法
|
||||
try {
|
||||
TestReportMainFrame.tr.sandMail(TestReportFrame.content.getText(),
|
||||
TestReportFrame.projectName.getText(),
|
||||
(TestReportFrame.Version.getText() + "版本测试报告"), TestReportFrame.range.getText(),
|
||||
new File(TestReportMainFrame.tr.getSavePath()
|
||||
+ TestReportMainFrame.tr.getFileName()
|
||||
+ ".zip"));
|
||||
} catch (DocumentException | MessagingException
|
||||
| IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
new File(TestReportMainFrame.tr.getSavePath()
|
||||
+ TestReportMainFrame.tr.getFileName() + ".zip")
|
||||
.delete();
|
||||
|
||||
frame.setVisible(false);
|
||||
// 弹出一个提示框,表示测试报告生成完毕
|
||||
JOptionPane.showMessageDialog(TestReportFrame.purpose, "邮件已发送成功,请在邮箱中查看");
|
||||
}
|
||||
});
|
||||
yes.setBounds(171, 498, 93, 23);
|
||||
contentPane.add(yes);
|
||||
|
||||
JButton no = new JButton("\u53D6\u6D88");
|
||||
no.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//隐藏窗口
|
||||
frame.setVisible(false);
|
||||
}
|
||||
});
|
||||
no.setBounds(331, 498, 93, 23);
|
||||
contentPane.add(no);
|
||||
|
||||
JButton refresh = new JButton("\u5237\u65B0");
|
||||
refresh.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//刷新数据,即调用初始化数据方法
|
||||
initData();
|
||||
}
|
||||
});
|
||||
refresh.setBounds(11, 498, 93, 23);
|
||||
contentPane.add(refresh);
|
||||
|
||||
JLabel label_2 = new JLabel("\u5185\u5BB9\u9884\u89C8\uFF1A");
|
||||
label_2.setBounds(10, 266, 94, 15);
|
||||
contentPane.add(label_2);
|
||||
|
||||
JScrollPane scrollPane_2 = new JScrollPane();
|
||||
scrollPane_2.setBounds(10, 291, 414, 197);
|
||||
contentPane.add(scrollPane_2);
|
||||
|
||||
content = new JTextArea();
|
||||
content.setLineWrap(true);
|
||||
scrollPane_2.setViewportView(content);
|
||||
}
|
||||
|
||||
public static void showFrame() {
|
||||
initData();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
public static void initData() {
|
||||
//根据项目名称获取邮件的收件人与抄送人
|
||||
String[][] strs = TestReportMainFrame.tr.getMailToAndCc(TestReportFrame.projectName.getText());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
//获取收件人
|
||||
for (String s : strs[0]) {
|
||||
sb.append(s + "\n");
|
||||
}
|
||||
sb.delete(sb.lastIndexOf("\n"), sb.length());
|
||||
|
||||
//填写收件人到界面中
|
||||
to.setText(sb.toString());
|
||||
|
||||
//清空存储的收件人
|
||||
sb.delete(0, sb.length());
|
||||
|
||||
//获取抄送人
|
||||
for (String s : strs[1]) {
|
||||
sb.append(s + "\n");
|
||||
}
|
||||
sb.delete(sb.lastIndexOf("\n"), sb.length());
|
||||
|
||||
//填写抄送人到界面中
|
||||
cc.setText(sb.toString());
|
||||
|
||||
String text = "";
|
||||
try {
|
||||
text = TestReportMainFrame.tr.getMailContent(TestReportFrame.content.getText(),
|
||||
TestReportFrame.projectName.getText(),
|
||||
(TestReportFrame.Version.getText() + "版本测试报告"), TestReportFrame.range.getText());
|
||||
} catch (DocumentException | MessagingException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//在预览信息中添加文本
|
||||
content.setText(text);
|
||||
}
|
||||
}
|
|
@ -1,824 +0,0 @@
|
|||
package pres.auxiliary.report.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerDateModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.WindowConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.report.AbstractReport.BugInformation;
|
||||
import pres.auxiliary.tool.ui.control.AutoNumberJTextArea;
|
||||
|
||||
/**
|
||||
* FileName: TestReportFrame.java
|
||||
*
|
||||
* 该界面是生成测试报告程序的主界面,可在此编辑测试报告的内容并生成测试报告
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @Deta 2018年4月26日 下午2:52:49
|
||||
* @version ver1.3
|
||||
*/
|
||||
public class TestReportFrame extends JFrame {
|
||||
private static final long serialVersionUID = 4597332795736199596L;
|
||||
private JPanel contentPane;
|
||||
private static JTextField showBugFilePath;
|
||||
protected static JTextField projectName;
|
||||
protected static JTextField Version;
|
||||
private JLabel label_2;
|
||||
protected static JSpinner startTime;
|
||||
private JLabel label_3;
|
||||
protected static JSpinner endTime;
|
||||
protected static JTextField range;
|
||||
protected static JTextField person;
|
||||
protected static JTextArea purpose;
|
||||
protected static JTextArea gist;
|
||||
protected static JSpinner activeOneBug;
|
||||
protected static JSpinner activeTwoBug;
|
||||
protected static JSpinner activeThreeBug;
|
||||
protected static JSpinner activeFourBug;
|
||||
protected static JSpinner newOneBug;
|
||||
protected static JSpinner newTwoBug;
|
||||
protected static JSpinner newThreeBug;
|
||||
protected static JSpinner newFourBug;
|
||||
protected static JCheckBox isPass;
|
||||
protected static JTextArea content;
|
||||
|
||||
static TestReportFrame frame = new TestReportFrame();
|
||||
private JButton printReport;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
static void Main() {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame.setVisible(true);
|
||||
// 设置窗体显示在屏幕中心
|
||||
frame.setLocationRelativeTo(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public TestReportFrame() {
|
||||
setResizable(false);
|
||||
setTitle("\u6D4B\u8BD5\u62A5\u544A\u751F\u6210\u5668");
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setBounds(100, 100, 634, 791);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
contentPane.setLayout(null);
|
||||
|
||||
JLabel lblNewLabel = new JLabel("Bug\u5217\u8868\u6587\u4EF6\u4F4D\u7F6E\uFF1A");
|
||||
lblNewLabel.setBounds(10, 10, 118, 15);
|
||||
contentPane.add(lblNewLabel);
|
||||
|
||||
showBugFilePath = new JTextField();
|
||||
showBugFilePath.setEditable(false);
|
||||
showBugFilePath.setBounds(127, 7, 361, 21);
|
||||
contentPane.add(showBugFilePath);
|
||||
showBugFilePath.setColumns(10);
|
||||
|
||||
JButton button = new JButton("\u4FEE\u6539");
|
||||
button.setBounds(498, 6, 69, 23);
|
||||
contentPane.add(button);
|
||||
|
||||
JLabel label = new JLabel("\u9879\u76EE\u540D\u79F0\uFF1A");
|
||||
label.setBounds(10, 38, 69, 15);
|
||||
contentPane.add(label);
|
||||
|
||||
projectName = new JTextField();
|
||||
projectName.setBounds(82, 35, 485, 21);
|
||||
contentPane.add(projectName);
|
||||
projectName.setColumns(10);
|
||||
|
||||
JLabel label_1 = new JLabel("\u7248\u672C\u4FE1\u606F\uFF1A");
|
||||
label_1.setBounds(10, 69, 69, 15);
|
||||
contentPane.add(label_1);
|
||||
|
||||
Version = new JTextField();
|
||||
Version.setColumns(10);
|
||||
Version.setBounds(82, 66, 485, 21);
|
||||
contentPane.add(Version);
|
||||
|
||||
label_2 = new JLabel("\u6D4B\u8BD5\u65F6\u95F4\uFF1A");
|
||||
label_2.setBounds(10, 125, 69, 15);
|
||||
contentPane.add(label_2);
|
||||
|
||||
SpinnerDateModel model = new SpinnerDateModel();
|
||||
startTime = new JSpinner(model);
|
||||
startTime.setValue(new Date());
|
||||
JSpinner.DateEditor de_startTime = new JSpinner.DateEditor(startTime, "yyyy.MM.dd");
|
||||
startTime.setEditor(de_startTime);
|
||||
startTime.setBounds(82, 122, 93, 28);
|
||||
contentPane.add(startTime);
|
||||
|
||||
label_3 = new JLabel("\uFF5E");
|
||||
label_3.setBounds(185, 129, 22, 15);
|
||||
contentPane.add(label_3);
|
||||
|
||||
SpinnerDateModel model2 = new SpinnerDateModel();
|
||||
endTime = new JSpinner(model2);
|
||||
endTime.setValue(new Date());
|
||||
JSpinner.DateEditor de_endTime = new JSpinner.DateEditor(endTime, "yyyy.MM.dd");
|
||||
endTime.setEditor(de_endTime);
|
||||
endTime.setBounds(206, 122, 93, 28);
|
||||
contentPane.add(endTime);
|
||||
|
||||
person = new JTextField();
|
||||
person.setColumns(10);
|
||||
person.setBounds(82, 160, 485, 21);
|
||||
contentPane.add(person);
|
||||
|
||||
JLabel label_4 = new JLabel("\u6D4B\u8BD5\u6210\u5458\uFF1A");
|
||||
label_4.setBounds(10, 163, 69, 15);
|
||||
contentPane.add(label_4);
|
||||
|
||||
JLabel label_5 = new JLabel("\u6D4B\u8BD5\u76EE\u7684\uFF1A");
|
||||
label_5.setBounds(10, 191, 69, 15);
|
||||
contentPane.add(label_5);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane();
|
||||
scrollPane.setBounds(10, 216, 557, 70);
|
||||
contentPane.add(scrollPane);
|
||||
|
||||
purpose = new AutoNumberJTextArea();
|
||||
purpose.setLineWrap(true);
|
||||
scrollPane.setViewportView(purpose);
|
||||
|
||||
JLabel label_6 = new JLabel("\u6D4B\u8BD5\u4F9D\u636E\uFF1A");
|
||||
label_6.setBounds(10, 296, 69, 15);
|
||||
contentPane.add(label_6);
|
||||
|
||||
JScrollPane scrollPane_1 = new JScrollPane();
|
||||
scrollPane_1.setBounds(10, 321, 557, 70);
|
||||
contentPane.add(scrollPane_1);
|
||||
|
||||
gist = new AutoNumberJTextArea();
|
||||
gist.setLineWrap(true);
|
||||
scrollPane_1.setViewportView(gist);
|
||||
|
||||
JLabel lblbug = new JLabel("\u6FC0\u6D3BBug\u6570\uFF1A");
|
||||
lblbug.setBounds(10, 401, 84, 15);
|
||||
contentPane.add(lblbug);
|
||||
|
||||
JLabel label_7 = new JLabel("\u4E00\u7EA7\uFF1A");
|
||||
label_7.setBounds(10, 433, 44, 15);
|
||||
contentPane.add(label_7);
|
||||
|
||||
activeOneBug = new JSpinner();
|
||||
activeOneBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
activeOneBug.setBounds(48, 426, 46, 28);
|
||||
contentPane.add(activeOneBug);
|
||||
|
||||
JLabel label_8 = new JLabel("\u4E8C\u7EA7\uFF1A");
|
||||
label_8.setBounds(123, 433, 44, 15);
|
||||
contentPane.add(label_8);
|
||||
|
||||
activeTwoBug = new JSpinner();
|
||||
activeTwoBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
activeTwoBug.setBounds(161, 426, 46, 28);
|
||||
contentPane.add(activeTwoBug);
|
||||
|
||||
JLabel label_9 = new JLabel("\u4E09\u7EA7\uFF1A");
|
||||
label_9.setBounds(235, 433, 44, 15);
|
||||
contentPane.add(label_9);
|
||||
|
||||
activeThreeBug = new JSpinner();
|
||||
activeThreeBug.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
activeThreeBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
activeThreeBug.setBounds(273, 426, 46, 28);
|
||||
contentPane.add(activeThreeBug);
|
||||
|
||||
JLabel label_10 = new JLabel("\u56DB\u7EA7\uFF1A");
|
||||
label_10.setBounds(345, 433, 44, 15);
|
||||
contentPane.add(label_10);
|
||||
|
||||
activeFourBug = new JSpinner();
|
||||
activeFourBug.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
activeFourBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
activeFourBug.setBounds(383, 426, 46, 28);
|
||||
contentPane.add(activeFourBug);
|
||||
|
||||
JLabel lblbug_1 = new JLabel("\u65B0\u63D0\u4EA4Bug\u6570\uFF1A");
|
||||
lblbug_1.setBounds(10, 458, 93, 15);
|
||||
contentPane.add(lblbug_1);
|
||||
|
||||
JLabel label_12 = new JLabel("\u4E00\u7EA7\uFF1A");
|
||||
label_12.setBounds(10, 488, 44, 15);
|
||||
contentPane.add(label_12);
|
||||
|
||||
newOneBug = new JSpinner();
|
||||
newOneBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
newOneBug.setBounds(48, 481, 46, 28);
|
||||
contentPane.add(newOneBug);
|
||||
|
||||
JLabel label_13 = new JLabel("\u4E8C\u7EA7\uFF1A");
|
||||
label_13.setBounds(123, 488, 44, 15);
|
||||
contentPane.add(label_13);
|
||||
|
||||
newTwoBug = new JSpinner();
|
||||
newTwoBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
newTwoBug.setBounds(161, 481, 46, 28);
|
||||
contentPane.add(newTwoBug);
|
||||
|
||||
JLabel label_14 = new JLabel("\u4E09\u7EA7\uFF1A");
|
||||
label_14.setBounds(235, 488, 44, 15);
|
||||
contentPane.add(label_14);
|
||||
|
||||
newThreeBug = new JSpinner();
|
||||
newThreeBug.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
newThreeBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
newThreeBug.setBounds(273, 481, 46, 28);
|
||||
contentPane.add(newThreeBug);
|
||||
|
||||
JLabel label_15 = new JLabel("\u56DB\u7EA7\uFF1A");
|
||||
label_15.setBounds(345, 488, 44, 15);
|
||||
contentPane.add(label_15);
|
||||
|
||||
newFourBug = new JSpinner();
|
||||
newFourBug.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
newFourBug.setModel(new SpinnerNumberModel(0, 0, null, 1));
|
||||
newFourBug.setBounds(383, 481, 46, 28);
|
||||
contentPane.add(newFourBug);
|
||||
|
||||
JLabel label_11 = new JLabel("\u662F\u5426\u901A\u8FC7\uFF1A");
|
||||
label_11.setBounds(447, 444, 69, 15);
|
||||
contentPane.add(label_11);
|
||||
|
||||
isPass = new JCheckBox("\u4E0D\u901A\u8FC7");
|
||||
isPass.setToolTipText(
|
||||
"\u6839\u636E\u4E00\u3001\u4E8C\u7EA7Bug\u7684\u6570\u91CF\u81EA\u52A8\u66F4\u6539\uFF0C\u4E5F\u53EF\u4EE5\u624B\u52A8\u66F4\u6539");
|
||||
isPass.addChangeListener(new ChangeListener() {
|
||||
// 不添加状态改变事件会导致增加一二级BUG数后复选框不自动勾选
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if (isPass.isSelected()) {
|
||||
isPass.setText("通过");
|
||||
} else {
|
||||
isPass.setText("不通过");
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
isPass.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (isPass.isSelected()) {
|
||||
isPass.setText("通过");
|
||||
} else {
|
||||
isPass.setText("不通过");
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
isPass.setBounds(447, 465, 103, 23);
|
||||
contentPane.add(isPass);
|
||||
|
||||
final JButton createReport = new JButton("\u751F\u6210\u62A5\u544A");
|
||||
createReport.setBounds(10, 672, 93, 23);
|
||||
contentPane.add(createReport);
|
||||
|
||||
final JButton sandMail = new JButton("\u53D1\u9001\u90AE\u4EF6");
|
||||
sandMail.setEnabled(false);
|
||||
sandMail.setBounds(241, 672, 93, 23);
|
||||
contentPane.add(sandMail);
|
||||
|
||||
JButton reset = new JButton("\u91CD\u7F6E");
|
||||
reset.setBounds(359, 672, 93, 23);
|
||||
contentPane.add(reset);
|
||||
|
||||
JButton showCode = new JButton("\u751F\u6210\u4EE3\u7801");
|
||||
showCode.setBounds(474, 672, 93, 23);
|
||||
contentPane.add(showCode);
|
||||
|
||||
JLabel label_16 = new JLabel("\u6D4B\u8BD5\u8303\u56F4\uFF1A");
|
||||
label_16.setBounds(10, 97, 69, 15);
|
||||
contentPane.add(label_16);
|
||||
|
||||
range = new JTextField();
|
||||
range.setColumns(10);
|
||||
range.setBounds(82, 94, 485, 21);
|
||||
contentPane.add(range);
|
||||
|
||||
JLabel label_17 = new JLabel("\u62A5\u544A\u5185\u5BB9\uFF1A");
|
||||
label_17.setBounds(10, 519, 69, 15);
|
||||
contentPane.add(label_17);
|
||||
|
||||
JScrollPane scrollPane_2 = new JScrollPane();
|
||||
scrollPane_2.setBounds(10, 544, 557, 118);
|
||||
contentPane.add(scrollPane_2);
|
||||
|
||||
content = new JTextArea();
|
||||
content.setToolTipText(
|
||||
"\u6D4B\u8BD5\u62A5\u544A\u7684\u5185\u5BB9\u53EF\u6839\u636E\u5176\u4E0A\u65B9\u7684\u8BBE\u7F6E\u81EA\u52A8\u53D8\u66F4\u6587\u5B57\uFF0C\u4E5F\u53EF\u4EE5\u5728\u6B64\u5904\u66F4\u6539\uFF0C\u66F4\u6539\u540E\u6587\u5B57\u5C06\u53CD\u6620\u5230\u6D4B\u8BD5\u62A5\u544A\u548C\u90AE\u4EF6\u5185\u5BB9\u4E2D");
|
||||
content.setLineWrap(true);
|
||||
scrollPane_2.setViewportView(content);
|
||||
|
||||
printReport = new JButton("\u6253\u5370\u62A5\u544A");
|
||||
printReport.setEnabled(false);
|
||||
printReport.setBounds(125, 672, 93, 23);
|
||||
contentPane.add(printReport);
|
||||
|
||||
final JButton refreshBug = new JButton("\u5237\u65B0Bug\u6570\u91CF");
|
||||
refreshBug.setToolTipText(
|
||||
"\u80FD\u6839\u636E\u6D4B\u8BD5\u65F6\u95F4\u6765\u91CD\u65B0\u83B7\u53D6Bug\u6570\u91CF");
|
||||
refreshBug.setBounds(326, 124, 126, 23);
|
||||
contentPane.add(refreshBug);
|
||||
|
||||
activeOneBug.addChangeListener(new ChangeListener() {
|
||||
// 判断激活或者新提交的BUG是否有一级与二级的BUG,若有,则将是否通过的选择框设为勾选状态
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if ((int) activeOneBug.getValue() > 0 || (int) activeTwoBug.getValue() > 0
|
||||
|| (int) newOneBug.getValue() > 0 || (int) newTwoBug.getValue() > 0) {
|
||||
isPass.setSelected(false);
|
||||
} else {
|
||||
isPass.setSelected(true);
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
|
||||
activeTwoBug.addChangeListener(new ChangeListener() {
|
||||
// 判断激活或者新提交的BUG是否有一级与二级的BUG,若有,则将是否通过的选择框设为勾选状态
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if ((int) activeOneBug.getValue() > 0 || (int) activeTwoBug.getValue() > 0
|
||||
|| (int) newOneBug.getValue() > 0 || (int) newTwoBug.getValue() > 0) {
|
||||
isPass.setSelected(false);
|
||||
} else {
|
||||
isPass.setSelected(true);
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
|
||||
newOneBug.addChangeListener(new ChangeListener() {
|
||||
// 判断激活或者新提交的BUG是否有一级与二级的BUG,若有,则将是否通过的选择框设为勾选状态
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if ((int) activeOneBug.getValue() > 0 || (int) activeTwoBug.getValue() > 0
|
||||
|| (int) newOneBug.getValue() > 0 || (int) newTwoBug.getValue() > 0) {
|
||||
isPass.setSelected(false);
|
||||
} else {
|
||||
isPass.setSelected(true);
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
|
||||
newTwoBug.addChangeListener(new ChangeListener() {
|
||||
// 判断激活或者新提交的BUG是否有一级与二级的BUG,若有,则将是否通过的选择框设为勾选状态
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if ((int) activeOneBug.getValue() > 0 || (int) activeTwoBug.getValue() > 0
|
||||
|| (int) newOneBug.getValue() > 0 || (int) newTwoBug.getValue() > 0) {
|
||||
isPass.setSelected(false);
|
||||
} else {
|
||||
isPass.setSelected(true);
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 修改按钮的点击事件
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
frame.setVisible(false);
|
||||
sandMail.setEnabled(false);
|
||||
printReport.setEnabled(false);
|
||||
refreshBug.setEnabled(true);
|
||||
TestReportMainFrame.frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 生成报告按钮点击事件
|
||||
createReport.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 弹出一个确认弹框的方法
|
||||
// JOptionPane.showMessageDialog(confirm, "未选择测试用例文件");
|
||||
// System.out.println(endTime.getValue().toString());
|
||||
|
||||
String[] s = TestReportMainFrame.s;
|
||||
|
||||
// 拼接测试时间
|
||||
StringBuilder time = new StringBuilder();
|
||||
time.append(new SimpleDateFormat("yyyy.MM.dd").format(startTime.getValue()));
|
||||
time.append("-");
|
||||
time.append(new SimpleDateFormat("yyyy.MM.dd").format(endTime.getValue()));
|
||||
|
||||
TestReportMainFrame.tr.setFileName(Version.getText() + "版本测试报告");
|
||||
// new File(TestReportMainFrame.bugFileEdit.getText()).delete();
|
||||
try {
|
||||
TestReportMainFrame.tr.createReport(projectName.getText(), Version.getText(), time.toString(),
|
||||
person.getText(), range.getText(), purpose.getText(), gist.getText(), content.getText(),
|
||||
("附:" + Version.getText() + "版本Bug汇总表"));
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 生成报告时需要更新手动输入的BUG数量,此时需要重新获取并存储BUG数量,之后写入xml文件中
|
||||
s[0] = projectName.getText();
|
||||
s[1] = Version.getText().split("Ver")[1];
|
||||
s[2] = String.valueOf(newOneBug.getValue());
|
||||
s[3] = String.valueOf(newTwoBug.getValue());
|
||||
s[4] = String.valueOf(newThreeBug.getValue());
|
||||
s[5] = String.valueOf(newFourBug.getValue());
|
||||
|
||||
// 循环,删除time变量中所有的“.”
|
||||
while (true) {
|
||||
// 判断time中是否还包含“.”,没有则结束循环
|
||||
if (time.indexOf(".") == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 删除“.”
|
||||
time.deleteCharAt(time.indexOf("."));
|
||||
}
|
||||
|
||||
try {
|
||||
TestReportMainFrame.tr.writeVersionBugNumber(s, time.toString());
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 弹出一个提示框,表示测试报告生成完毕
|
||||
JOptionPane.showMessageDialog(purpose, "测试报告生成完毕,详见:" + TestReportMainFrame.tr.getSavePath()
|
||||
+ TestReportMainFrame.tr.getFileName() + "\\" + TestReportMainFrame.tr.getFileName() + ".docx");
|
||||
|
||||
sandMail.setEnabled(true);
|
||||
printReport.setEnabled(true);
|
||||
refreshBug.setEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 打印报告按钮点击事件
|
||||
printReport.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 弹出提示框,提示用户确认发送邮件的信息无误后,方可发送邮件
|
||||
int choose = JOptionPane.showConfirmDialog(purpose, "请确认测试报告内容无误后,点击“是”按钮来打印测试报告");
|
||||
|
||||
// 若用户点击“否”或“取消”按钮,则终止方法运行
|
||||
if (choose != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行发送邮件的方法
|
||||
try {
|
||||
TestReportMainFrame.tr.printReport(
|
||||
new File(TestReportMainFrame.tr.getSavePath() + Version.getText() + "版本测试报告\\"
|
||||
+ Version.getText() + "版本测试报告.docx"),
|
||||
new SAXReader().read(TestReportMainFrame.tr.xml).getRootElement().element("report")
|
||||
.attributeValue("print_name"));
|
||||
} catch (Exception e1) {
|
||||
}
|
||||
|
||||
// 弹出一个提示框,表示测试报告生成完毕
|
||||
JOptionPane.showMessageDialog(purpose, "测试报告已进入打印队列,网络问题可能会造成延迟,若长时间打印机无反应,则打印可能失败了");
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 发送邮件按钮点击事件
|
||||
sandMail.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SandMailFrame.showFrame();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 重置按钮点击事件
|
||||
reset.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
iniData();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 生成代码按钮点击事件
|
||||
showCode.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 计算测试时间(天数)
|
||||
long time = ((Date) (endTime.getValue())).getTime() - ((Date) (startTime.getValue())).getTime();
|
||||
|
||||
// TODO 由于平板上无法完成界面的编辑,故先将代码存储,回去后编辑文本域,使其反映到文本域上
|
||||
// 用于存储生成的代码
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
code.append("//TODO 若需要包名,请自行添加\n");
|
||||
code.append("//package \n\n");
|
||||
code.append("import java.io.File;\n");
|
||||
code.append("import java.io.IOException;\n");
|
||||
code.append("import java.io.UnsupportedEncodingException;\n\n");
|
||||
code.append("import javax.mail.MessagingException;\n\n");
|
||||
code.append("import org.dom4j.DocumentException;\n\n");
|
||||
code.append("import pres.auxiliary.report.TestReport;\n\n");
|
||||
|
||||
code.append("public class ReportCode {\n");
|
||||
code.append("\tpublic static void main(String[] args) {\n");
|
||||
|
||||
code.append("\t\tTestReport tr = new TestReport();\n");
|
||||
code.append("\t\t//设置测试报告保存位置\n");
|
||||
code.append("\t\t//TODO 此处需要自行将单个反斜杠变为两个反斜杠,否则会报错\n");
|
||||
code.append("\t\ttr.setSavePath(\"" + TestReportMainFrame.tr.getSavePath() + "\");\n");
|
||||
code.append("\t\t//创建测试报告\n");
|
||||
code.append("\t\t//TODO 此处需要自行将单个反斜杠变为两个反斜杠,否则会报错\n");
|
||||
code.append("\t\ttry {\n");
|
||||
code.append("\t\t\ttr.createReport(new File(\"" + TestReportMainFrame.bugFileEdit.getText() + "\"), "
|
||||
+ ((time / 1000 / 60 / 60 / 24) + 1) + ", \"" + person.getText() + "\", \"" + range.getText()
|
||||
+ "\");\n");
|
||||
code.append("\t\t} catch (IOException e1) {\n");
|
||||
code.append("\t\t\te1.printStackTrace();\n");
|
||||
code.append("\t\t}\n\n");
|
||||
|
||||
code.append("\t\t//发送邮件,可按需自行放开注释\n");
|
||||
code.append("\t\t/*\n");
|
||||
code.append("\t\ttry {\n");
|
||||
code.append("\t\t\ttr.sandMail(tr.getMailContent(), \"" + projectName.getText() + "版本测试报告" + "\", \""
|
||||
+ Version.getText() + "\", new File(tr.getSavePath() + tr.getFileName() + \".zip\"));\n");
|
||||
code.append("\t\t} catch (UnsupportedEncodingException e1) {\n");
|
||||
code.append("\t\t\te1.printStackTrace();\n");
|
||||
code.append("\t\t} catch (DocumentException e1) {\n");
|
||||
code.append("\t\t\te1.printStackTrace();\n");
|
||||
code.append("\t\t} catch (MessagingException e1) {\n");
|
||||
code.append("\t\t\te1.printStackTrace();\n");
|
||||
code.append("\t\t} catch (IOException e1) {\n");
|
||||
code.append("\t\t\te1.printStackTrace();\n");
|
||||
code.append("\t\t}\n");
|
||||
code.append("\t\t*/\n\n");
|
||||
|
||||
code.append("\t\t//打印测试报告,可按需自行放开注释\n");
|
||||
code.append("\t\t/*\n");
|
||||
code.append("\t\ttry {\n");
|
||||
code.append(
|
||||
"\t\t\ttr.printReport(new File(tr.getSavePath() + tr.getFileName() + \".docx\"), new SAXReader().read(new File(\"ConfigurationFiles/ReportConfigurationFile/TestReportConfiguration.xml\")).getRootElement().element(\"report\").attributeValue(\"print_name\"));\n");
|
||||
code.append("\t\t} catch (DocumentException e) {\n");
|
||||
code.append("\t\t\te.printStackTrace();\n");
|
||||
code.append("\t\t}\n");
|
||||
code.append("\t\t*/\n\n");
|
||||
|
||||
code.append("\t\t//若XML文件配置无误,则可调用以下代码:\n");
|
||||
code.append("\t\t//TestReport tr = new TestReport();\n");
|
||||
code.append("\t\t//tr.setSavePath(\"" + TestReportMainFrame.tr.getSavePath() + "\");\n");
|
||||
code.append("\t\t//tr.autoWriteReport(true, true)\n");
|
||||
code.append("\t}\n");
|
||||
code.append("}\n");
|
||||
// System.out.println(code.toString());
|
||||
|
||||
// 创建存储测试报告代码存放的文件夹
|
||||
File f = new File("Code\\Report\\");
|
||||
f.mkdirs();
|
||||
|
||||
// 创建写入流,保存生成的代码
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
bw = new BufferedWriter(new FileWriter(new File(f + "\\ReportCode.java")));
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 写入代码
|
||||
try {
|
||||
bw.write(code.toString());
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 关闭流
|
||||
try {
|
||||
bw.close();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 弹出文件夹
|
||||
try {
|
||||
java.awt.Desktop.getDesktop().open(f);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 弹出一个提示框,表示测试报告生成完毕
|
||||
JOptionPane.showMessageDialog(purpose,
|
||||
"代码已生成,详见项目路径下:" + new File(f + "\\ReportCode.java").getAbsolutePath());
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 刷新Bug数量按钮事件
|
||||
refreshBug.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 读取BUG列表文件,重新刷新BUG数量
|
||||
// 读取Bug列表文件
|
||||
String[] ss = null;
|
||||
try {
|
||||
ss = TestReportMainFrame.tr.readFile(new File(TestReportMainFrame.bugFileEdit.getText()),
|
||||
projectName.getText(), Version.getText().split("Ver")[1],
|
||||
new SimpleDateFormat("yyyyMMdd").format(startTime.getValue()),
|
||||
new SimpleDateFormat("yyyyMMdd").format(endTime.getValue()));
|
||||
} catch (NumberFormatException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
activeOneBug.setValue(Integer.valueOf(ss[6]));
|
||||
activeTwoBug.setValue(Integer.valueOf(ss[7]));
|
||||
activeThreeBug.setValue(Integer.valueOf(ss[8]));
|
||||
activeFourBug.setValue(Integer.valueOf(ss[9]));
|
||||
|
||||
newOneBug.setValue(Integer.valueOf(ss[2]));
|
||||
newTwoBug.setValue(Integer.valueOf(ss[3]));
|
||||
newThreeBug.setValue(Integer.valueOf(ss[4]));
|
||||
newFourBug.setValue(Integer.valueOf(ss[5]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于在其他界面需要显示窗口时调用
|
||||
*/
|
||||
public static void showFrame() {
|
||||
iniData();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void iniData() {
|
||||
// 设置读取到的参数
|
||||
showBugFilePath.setText(TestReportMainFrame.bugFileEdit.getText());
|
||||
projectName.setText(TestReportMainFrame.s[0]);
|
||||
Version.setText(TestReportMainFrame.s[0] + "Ver" + TestReportMainFrame.s[1]);
|
||||
try {
|
||||
startTime.setValue(new SimpleDateFormat("yyyy.MM.dd").parse(TestReportMainFrame.s[14]));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
endTime.setValue(new SimpleDateFormat("yyyy.MM.dd").parse(TestReportMainFrame.s[15]));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
range.setText(TestReportMainFrame.s[16]);
|
||||
person.setText(TestReportMainFrame.s[17]);
|
||||
purpose.setText(TestReportMainFrame.s[18]);
|
||||
gist.setText(TestReportMainFrame.s[19]);
|
||||
|
||||
activeOneBug.setValue(Integer.valueOf(TestReportMainFrame.s[6]));
|
||||
activeTwoBug.setValue(Integer.valueOf(TestReportMainFrame.s[7]));
|
||||
activeThreeBug.setValue(Integer.valueOf(TestReportMainFrame.s[8]));
|
||||
activeFourBug.setValue(Integer.valueOf(TestReportMainFrame.s[9]));
|
||||
newOneBug.setValue(Integer.valueOf(TestReportMainFrame.s[2]));
|
||||
newTwoBug.setValue(Integer.valueOf(TestReportMainFrame.s[3]));
|
||||
newThreeBug.setValue(Integer.valueOf(TestReportMainFrame.s[4]));
|
||||
newFourBug.setValue(Integer.valueOf(TestReportMainFrame.s[5]));
|
||||
|
||||
// 设置是否通过的复选框
|
||||
if ((int) activeOneBug.getValue() > 0 || (int) activeTwoBug.getValue() > 0 || (int) newOneBug.getValue() > 0
|
||||
|| (int) newTwoBug.getValue() > 0) {
|
||||
isPass.setSelected(false);
|
||||
} else {
|
||||
isPass.setSelected(true);
|
||||
}
|
||||
|
||||
updataContent();
|
||||
}
|
||||
|
||||
private static void updataContent() {
|
||||
StringBuilder testResult = new StringBuilder();
|
||||
if ((int) activeOneBug.getValue() != 0 || (int) activeTwoBug.getValue() != 0
|
||||
|| (int) activeThreeBug.getValue() != 0 || (int) activeFourBug.getValue() != 0) {
|
||||
testResult.append("回归测试发现并激活" + String.valueOf((int) activeOneBug.getValue() + (int) activeTwoBug.getValue()
|
||||
+ (int) activeThreeBug.getValue() + (int) activeFourBug.getValue()) + "个Bug,其中,");
|
||||
if ((int) activeOneBug.getValue() != 0) {
|
||||
testResult.append("一级Bug有" + (int) activeOneBug.getValue() + "个,");
|
||||
}
|
||||
if ((int) activeTwoBug.getValue() != 0) {
|
||||
testResult.append("二级Bug有" + (int) activeTwoBug.getValue() + "个,");
|
||||
}
|
||||
if ((int) activeThreeBug.getValue() != 0) {
|
||||
testResult.append("三级Bug有" + (int) activeThreeBug.getValue() + "个,");
|
||||
}
|
||||
if ((int) activeFourBug.getValue() != 0) {
|
||||
testResult.append("四级Bug有" + (int) activeFourBug.getValue() + "个,");
|
||||
}
|
||||
testResult.replace(testResult.lastIndexOf(","), testResult.lastIndexOf(",") + 1, ";");
|
||||
}
|
||||
testResult.append("新发现并提交" + String.valueOf((int) newOneBug.getValue() + (int) newTwoBug.getValue()
|
||||
+ (int) newThreeBug.getValue() + (int) newFourBug.getValue()) + "个Bug,其中,");
|
||||
testResult.append("一级Bug有" + (int) newOneBug.getValue() + "个,");
|
||||
testResult.append("二级Bug有" + (int) newTwoBug.getValue() + "个,");
|
||||
testResult.append("三级Bug有" + (int) newThreeBug.getValue() + "个,");
|
||||
testResult.append("四级Bug有" + (int) newFourBug.getValue() + "个;");
|
||||
testResult.append("详情请查看禅道系统或者问题汇总中的Bug记录详情。");
|
||||
// 多选框是否被勾选,根据判断给出相应的文字结果
|
||||
if (!isPass.isSelected()) {
|
||||
testResult.append("由于该版本存在二级以上的Bug,根据测试依据软件测试通过准则,判定该版本测试结果为:不通过。\n");
|
||||
} else {
|
||||
testResult.append("由于该版本未发现二级以上的Bug,根据测试依据软件测试通过准则,判定该版本测试结果为:通过。\n");
|
||||
}
|
||||
|
||||
//若有严重的BUG存在,则获取其信息列表,之后将严重的BUG信息放入报告中
|
||||
if ( (int) newOneBug.getValue() != 0 || (int) newTwoBug.getValue() != 0) {
|
||||
List<BugInformation> bugInformation = TestReportMainFrame.tr.getBugInformations();
|
||||
testResult.append("其中,严重的BUG基本信息如下:\n");
|
||||
for (int i = 0; i < bugInformation.size(); i++) {
|
||||
testResult.append("●");
|
||||
testResult.append(bugInformation.get(i).bugTitle);
|
||||
testResult.append("("+ bugInformation.get(i).bugLv + "级BUG,禅道编号为:" + bugInformation.get(i).bugID + ")\n");
|
||||
}
|
||||
}
|
||||
|
||||
//添加未处理的BUG数量
|
||||
if ( Integer.valueOf(TestReportMainFrame.s[10]) != 0 || Integer.valueOf(TestReportMainFrame.s[11]) != 0 ||
|
||||
Integer.valueOf(TestReportMainFrame.s[12]) != 0 || Integer.valueOf(TestReportMainFrame.s[13]) != 0 ) {
|
||||
testResult.append("在往期版本中,发现存在未解决、延期处理的一、二级Bug,总数为" +
|
||||
(Integer.valueOf(TestReportMainFrame.s[10]) +
|
||||
Integer.valueOf(TestReportMainFrame.s[11]) +
|
||||
Integer.valueOf(TestReportMainFrame.s[12]) +
|
||||
Integer.valueOf(TestReportMainFrame.s[13])) + "个,其中,");
|
||||
if ( Integer.valueOf(TestReportMainFrame.s[10]) != 0 ) {
|
||||
testResult.append("未解决的一级Bug有" + Integer.valueOf(TestReportMainFrame.s[10]) + "个,");
|
||||
}
|
||||
if ( Integer.valueOf(TestReportMainFrame.s[11]) != 0 ) {
|
||||
testResult.append("未解决二级Bug有" + Integer.valueOf(TestReportMainFrame.s[11]) + "个,");
|
||||
}
|
||||
if ( Integer.valueOf(TestReportMainFrame.s[12]) != 0 ) {
|
||||
testResult.append("延期解决的一级Bug有" + Integer.valueOf(TestReportMainFrame.s[12]) + "个,");
|
||||
}
|
||||
if ( Integer.valueOf(TestReportMainFrame.s[13]) != 0 ) {
|
||||
testResult.append("延期解决的二级Bug有" + Integer.valueOf(TestReportMainFrame.s[13]) + "个,");
|
||||
}
|
||||
testResult.append("望技术经理、开发人员及项目经理重视!\n");
|
||||
|
||||
}
|
||||
|
||||
content.setText(testResult.toString());
|
||||
}
|
||||
}
|
|
@ -1,412 +0,0 @@
|
|||
package pres.auxiliary.report.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.WindowConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import pres.auxiliary.report.TestReport;
|
||||
|
||||
/**
|
||||
* 测试报告主界面,用于设置报告生成位置以及Bug列表文件的位置
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*/
|
||||
public class TestReportMainFrame extends JFrame {
|
||||
private static final long serialVersionUID = 1L;
|
||||
static TestReport tr = new TestReport();
|
||||
|
||||
// 设置默认的文件保存位置
|
||||
static String saveFilePath = "C:\\AutoTest\\Report";
|
||||
|
||||
/**
|
||||
* 存储测试报告中的所有内容,以下是存储的信息:<br/>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>s[0]:项目名称</td>
|
||||
* <td>s[1]:当前版本</td>
|
||||
* <td>s[2]:1级BUG数量</td>
|
||||
* <td>s[3]:2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[4]:3级BUG数量</td>
|
||||
* <td>s[5]:4级BUG数量</td>
|
||||
* <td>s[6]:激活1级BUG数量</td>
|
||||
* <td>s[7]:激活2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[8]:激活3级BUG数量</td>
|
||||
* <td>s[9]:激活4级BUG数量</td>
|
||||
* <td>s[10]:未解决的1级BUG数量</td>
|
||||
* <td>s[11]:未解决的2级BUG数量</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[12]:延期解决的1级BUG数量</td>
|
||||
* <td>s[13]:延期解决的2级BUG数量</td>
|
||||
* <td>s[14]:测试开始时间</td>
|
||||
* <td>s[15]:测试结束时间</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>s[16]:测试范围</td>
|
||||
* <td>s[17]:测试人员</td>
|
||||
* <td>s[18]:测试目的</td>
|
||||
* <td>s[19]:测试依据</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <br/>
|
||||
* <font size="3"><b>千万不要随意改动顺序,需要添加则向下加,不要覆盖前面的!否则主界面会有BUG!</b></font>
|
||||
*
|
||||
*/
|
||||
static String[] s = new String[20];
|
||||
|
||||
private JPanel contentPane;
|
||||
static JTextField bugFileEdit;
|
||||
private JTextField reportSavePathEdit;
|
||||
|
||||
// 创建自身窗口
|
||||
static TestReportMainFrame frame = new TestReportMainFrame();
|
||||
|
||||
// 设置选择器,选择默认位置为C:\\AutoTest\\Report
|
||||
private JFileChooser chooser = new JFileChooser(new File(saveFilePath));
|
||||
private JButton createFileButton = new JButton("\u9009\u62E9\u6587\u4EF6");
|
||||
private JButton storyFileButton = new JButton("\u9009\u62E9\u6587\u4EF6");
|
||||
private JLabel createFileLabel = new JLabel(
|
||||
"\u8BF7\u9009\u62E9Bug\u6587\u4EF6\u4F4D\u7F6E\uFF1A");
|
||||
private JLabel storyFileLabel = new JLabel(
|
||||
"\u8BF7\u9009\u62E9\u62A5\u544A\u4FDD\u5B58\u4F4D\u7F6E\uFF1A");
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame.setVisible(true);
|
||||
// 设置窗体显示在屏幕中心
|
||||
frame.setLocationRelativeTo(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 可以通过该方法调用测试报告主界面
|
||||
*/
|
||||
public static void Main() {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame.setVisible(true);
|
||||
// 设置窗体显示在屏幕中心
|
||||
frame.setLocationRelativeTo(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public TestReportMainFrame() {
|
||||
setTitle("\u6D4B\u8BD5\u62A5\u544A\u751F\u6210\u5668");
|
||||
setResizable(false);
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setBounds(100, 100, 530, 207);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
contentPane.setLayout(null);
|
||||
|
||||
final JButton confirm = new JButton("\u786E\u5B9A");
|
||||
confirm.setBounds(193, 90, 93, 23);
|
||||
contentPane.add(confirm);
|
||||
|
||||
JButton cancel = new JButton("\u53D6\u6D88");
|
||||
// 添加取消按钮事件
|
||||
cancel.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 关闭窗体
|
||||
Runtime.getRuntime().exit(0);
|
||||
}
|
||||
});
|
||||
cancel.setBounds(369, 90, 93, 23);
|
||||
contentPane.add(cancel);
|
||||
|
||||
createFileLabel.setBounds(10, 14, 134, 15);
|
||||
contentPane.add(createFileLabel);
|
||||
|
||||
bugFileEdit = new JTextField();
|
||||
bugFileEdit.setEditable(false);
|
||||
bugFileEdit.setColumns(10);
|
||||
bugFileEdit.setBounds(143, 11, 218, 21);
|
||||
contentPane.add(bugFileEdit);
|
||||
createFileButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 不允许用户多选
|
||||
chooser.setMultiSelectionEnabled(false);
|
||||
// 1表示文件夹,0表示文件
|
||||
chooser.setFileSelectionMode(0);
|
||||
// 设置其选择的路径
|
||||
chooser.setCurrentDirectory(new File(bugFileEdit.getText()));
|
||||
// 判断文件是否存在,若存在,则设置在下一次打开选择文件窗口时能选中当前选择的文件
|
||||
if (bugFileEdit.getText().isEmpty()) {
|
||||
chooser.setSelectedFile(new File(bugFileEdit.getText()));
|
||||
}
|
||||
// 设置文件过滤器
|
||||
chooser.setFileFilter(new FileNameExtensionFilter(
|
||||
"请选择Excel文件或CSV文件(.xlsx .xls .csv)", "xlsx", "xls", "csv"));
|
||||
|
||||
// showOpenDialog(button)方法返回用户是否选择了文件夹
|
||||
int returnVal = chooser.showOpenDialog(createFileButton);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
// chooser.getSelectedFile()方法返回一个File对象
|
||||
bugFileEdit.setText(
|
||||
chooser.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
createFileButton.setBounds(371, 10, 93, 23);
|
||||
contentPane.add(createFileButton);
|
||||
|
||||
storyFileLabel.setBounds(10, 50, 134, 15);
|
||||
contentPane.add(storyFileLabel);
|
||||
|
||||
reportSavePathEdit = new JTextField();
|
||||
reportSavePathEdit.setText("C:\\AutoTest\\Report");
|
||||
reportSavePathEdit.setEditable(false);
|
||||
reportSavePathEdit.setColumns(10);
|
||||
reportSavePathEdit.setBounds(143, 47, 218, 21);
|
||||
contentPane.add(reportSavePathEdit);
|
||||
storyFileButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// 不允许用户多选
|
||||
chooser.setMultiSelectionEnabled(false);
|
||||
// 1表示文件夹,0表示文件
|
||||
chooser.setFileSelectionMode(1);
|
||||
// 设置其选择的路径
|
||||
chooser.setCurrentDirectory(
|
||||
new File(reportSavePathEdit.getText()));
|
||||
|
||||
// showOpenDialog(button)方法返回用户是否选择了文件夹
|
||||
int returnVal = chooser.showOpenDialog(storyFileButton);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
// chooser.getSelectedFile()方法返回一个File对象
|
||||
reportSavePathEdit.setText(
|
||||
chooser.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
//设置测试报告的存放路径
|
||||
tr.setSavePath(reportSavePathEdit.getText() + "\\");
|
||||
}
|
||||
});
|
||||
|
||||
storyFileButton.setBounds(371, 46, 93, 23);
|
||||
contentPane.add(storyFileButton);
|
||||
|
||||
JButton btnbug = new JButton("\u5BFC\u51FA\u6587\u4EF6");
|
||||
btnbug.setToolTipText("\u6839\u636E\u914D\u7F6E\u6587\u4EF6\u4E2D\u7684\u5185\u5BB9\uFF0C\u81EA\u52A8\u5411\u7985\u9053\u4E0A\u5BFC\u51FABug\u5217\u8868\u6587\u4EF6\uFF0C\u5E76\u5C06\u8DEF\u5F84\u586B\u5165Bug\u6587\u4EF6\u4F4D\u7F6E\u4E2D");
|
||||
btnbug.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Document dom = null;
|
||||
try {
|
||||
dom = new SAXReader().read(tr.xml);
|
||||
} catch (DocumentException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 获取基本信息并存储
|
||||
String url = dom.getRootElement().element("url")
|
||||
.attributeValue("url");
|
||||
String firefoxDirectory = dom.getRootElement()
|
||||
.element("firefox").attributeValue("directory");
|
||||
String firefoxProfiles = dom.getRootElement().element("firefox")
|
||||
.attributeValue("profiles");
|
||||
String username = dom.getRootElement().element("user")
|
||||
.attributeValue("username");
|
||||
String password = dom.getRootElement().element("user")
|
||||
.attributeValue("password");
|
||||
String search = dom.getRootElement().element("project")
|
||||
.attributeValue("name");
|
||||
String downloadSaveDirectory = dom.getRootElement()
|
||||
.element("firefox")
|
||||
.attributeValue("download_save_directory");
|
||||
String downloadFileName = dom.getRootElement().element("report")
|
||||
.attributeValue("download_file_name");
|
||||
|
||||
// 对禅道进行操作
|
||||
try {
|
||||
tr.operationZendao(firefoxDirectory, firefoxProfiles, url,
|
||||
username, password, search, downloadFileName);
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
bugFileEdit.setText(
|
||||
downloadSaveDirectory + downloadFileName + ".csv");
|
||||
}
|
||||
});
|
||||
btnbug.setBounds(10, 90, 93, 23);
|
||||
contentPane.add(btnbug);
|
||||
|
||||
// 添加确定按钮的点击事件
|
||||
confirm.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
frame.setVisible(false);
|
||||
|
||||
Document dom = null;
|
||||
try {
|
||||
dom = new SAXReader().read(tr.xml);
|
||||
} catch (DocumentException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 读取Bug列表文件
|
||||
String[] ss = null;
|
||||
try {
|
||||
ss = tr.readFile(new File(bugFileEdit.getText()),
|
||||
Integer.valueOf(dom.getRootElement()
|
||||
.element("report").attributeValue("days")));
|
||||
} catch (NumberFormatException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
// 记录从BUG列表文件中读取到的信息
|
||||
int i = 0;
|
||||
for (String str : ss) {
|
||||
s[i++] = str;
|
||||
}
|
||||
|
||||
// 存储测试开始和结束时间
|
||||
// 判断是否需要修改测试时间,若不需要则自动计算,需要则直接读取
|
||||
if (dom.getRootElement().element("report").element("content")
|
||||
.element("time").attributeValue("is_change")
|
||||
.equalsIgnoreCase("false")) {
|
||||
// 存储测试结束时间,即当前的时间
|
||||
Date d = new Date();
|
||||
// 设置测试开始时间,调用Calendar类进行处理
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
// 设置当前时间
|
||||
calendar.setTime(d);
|
||||
// 设置当前的天数减去测试时间,得到测试开始时间
|
||||
calendar.add(Calendar.DAY_OF_MONTH,
|
||||
(1 - Integer.valueOf(
|
||||
dom.getRootElement().element("report")
|
||||
.attributeValue("days"))));
|
||||
// 将得到的时间转换为Date进行返回
|
||||
d = calendar.getTime();
|
||||
// 存储测试开始时间
|
||||
s[i++] = new SimpleDateFormat("yyyy.MM.dd").format(d);
|
||||
|
||||
d = new Date();
|
||||
s[i++] = new SimpleDateFormat("yyyy.MM.dd").format(d);
|
||||
// d.setDate(d.getDate() - testDay);//方法过时
|
||||
} else {
|
||||
s[i++] = dom.getRootElement().element("report")
|
||||
.element("content").element("time")
|
||||
.element("starttime").getText();
|
||||
s[i++] = dom.getRootElement().element("report")
|
||||
.element("content").element("time")
|
||||
.element("endtime").getText();
|
||||
}
|
||||
|
||||
// 添加测试范围
|
||||
s[i++] = dom.getRootElement().element("report")
|
||||
.attributeValue("range");
|
||||
|
||||
// 添加参与测试的人员
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Element> l = dom.getRootElement().element("report")
|
||||
.element("testperson").elements();
|
||||
// 初始化存储的空间
|
||||
s[i] = "";
|
||||
for (Element ee : l) {
|
||||
if (ee.attributeValue("participation")
|
||||
.equalsIgnoreCase("true")) {
|
||||
s[i] += ee.attributeValue("name");
|
||||
s[i] += "、";
|
||||
}
|
||||
}
|
||||
// 截断字符串,使其不包含最后一个顿号
|
||||
s[i] = s[i].substring(0, s[i].lastIndexOf("、"));
|
||||
// 下标前进1
|
||||
i++;
|
||||
|
||||
// 添加测试目的
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Element> purposes = dom.getRootElement()
|
||||
.element("report").element("content").element("purpose")
|
||||
.elements();
|
||||
s[i] = "";
|
||||
// 获取测试目的
|
||||
for (int j = 0; j < purposes.size(); j++) {
|
||||
s[i] += ((j + 1) + "." + purposes.get(j).getText() + "\n");
|
||||
}
|
||||
// 截断字符串,使其不包含最后一个顿号
|
||||
s[i] = s[i].substring(0, s[i].lastIndexOf("\n"));
|
||||
// 下标前进1
|
||||
i++;
|
||||
|
||||
// 读取配置文件中的测试依据
|
||||
StringBuilder gist = new StringBuilder();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Element> gists = dom.getRootElement()
|
||||
.element("report").element("content").element("gist")
|
||||
.elements();
|
||||
s[i] = "";
|
||||
// 获取测试目的
|
||||
for (int j = 0; j < gists.size(); j++) {
|
||||
// 修改带${name}的
|
||||
if (gists.get(j).getText().indexOf("${name}") > -1) {
|
||||
gist.append((j + 1) + "." + gists.get(j).getText() + "\n");
|
||||
//注意,s[0]中存储的是项目名称
|
||||
gist.replace(gist.indexOf("$"), gist.indexOf("}") + 1, s[0]);
|
||||
} else {
|
||||
gist.append((j + 1) + "." + gists.get(j).getText() + "\n");
|
||||
}
|
||||
}
|
||||
s[i] = gist.toString();
|
||||
// 截断字符串,使其不包含最后一个换行符
|
||||
s[i] = s[i].substring(0, s[i].lastIndexOf("\n"));
|
||||
|
||||
// // 设置本窗体不显示
|
||||
frame.setVisible(false);
|
||||
// 弹出TestReportFrame界面
|
||||
TestReportFrame.showFrame();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package pres.auxiliary.report.ui;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>TestReportUI.java</p>
|
||||
* <p><b>用途:</b>用于设置界面的样式,并初始化测试报告UI界面</p>
|
||||
* <p><b>编码时间:</b>2018年12月19日 上午9:27:20</p>
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
public class TestReportUI {
|
||||
/**
|
||||
* 打开UI界面
|
||||
*/
|
||||
public static void open() {
|
||||
//设置BeautyEye L&F样式
|
||||
try{
|
||||
org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.launchBeautyEyeLNF();
|
||||
UIManager.put("RootPane.setupButtonVisible", false);
|
||||
}
|
||||
catch(Exception e){
|
||||
}
|
||||
|
||||
TestReportMainFrame.Main();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Condition.java</p>
|
||||
* <p><b>用途:</b>定义了条件类应包含的方法</p>
|
||||
* <p><b>编码时间:</b>2020年1月7日上午8:32:28</p>
|
||||
* <p><b>修改时间:</b>2020年1月7日上午8:32:28</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
* @param <T> 继承Condition类的条件类
|
||||
*/
|
||||
public abstract class Condition<T extends Condition<?>> {
|
||||
/**
|
||||
* 用于判断传入的数据是否满足相应的判断条件
|
||||
* @param <T> 相应的条件类对象
|
||||
* @param data 数据
|
||||
* @param condition 条件类对象
|
||||
* @return 是否满足相应的判断条件
|
||||
*/
|
||||
public abstract boolean judgeData(String data, T condition);
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FilterData {
|
||||
/**
|
||||
* 根据关键词,对一组文本进行筛选。通过boolean类型的传参来控制筛选的关键词的且或关系,
|
||||
* 当其为true时,则表示文本需要同时满足所有关键词时才能被返回;当其为false时,则表示只要
|
||||
* 满足其中一个关键词即可被返回。
|
||||
* @param words 文本组
|
||||
* @param judgeFull 是否需要所有关键词全部满足
|
||||
* @param keys 关键词组
|
||||
* @return 筛选后相应的文本组
|
||||
*/
|
||||
public static String[] filterText(String[] words, boolean judgeFull, String...keys) {
|
||||
//转换words数组为List集合
|
||||
List<String> wordList = Arrays.asList(words);
|
||||
|
||||
//调用重载的方法对词语进行筛选
|
||||
wordList = filterText(wordList, judgeFull, keys);
|
||||
|
||||
//将集合再转换为数组
|
||||
return wordList.toArray(new String[wordList.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据关键词,对一组文本进行筛选。通过boolean类型的传参来控制筛选的关键词的且或关系,
|
||||
* 当其为true时,则表示文本需要同时满足所有关键词时才能被返回;当其为false时,则表示只要
|
||||
* 满足其中一个关键词即可被返回。
|
||||
* @param wordList 文本组
|
||||
* @param judgeFull 是否需要所有关键词全部满足
|
||||
* @param keys 关键词组
|
||||
* @return 筛选后相应的文本组
|
||||
*/
|
||||
public static List<String> filterText(List<String> wordList, boolean judgeFull, String...keys) {
|
||||
return wordList.stream().filter(word -> judgeText(word, judgeFull, keys)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对文本是否包含关键词进行判断
|
||||
* @param text 文本
|
||||
* @param keyFull 是否需要所有关键词全部满足
|
||||
* @param keys 关键词
|
||||
* @return 判断结果
|
||||
*/
|
||||
private static boolean judgeText(String text, boolean judgeFull, String... keys) {
|
||||
//遍历所有的关键词
|
||||
for (String key : keys) {
|
||||
//判断文本是否包含关键词
|
||||
if (text.indexOf(key) > -1) {
|
||||
//若文本包含关键词,且keyFull为false,则表示无需判断所有的关键词,但文本包含关键词,可直接结束循环
|
||||
if (!judgeFull) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
//若文本不包含关键词,且keyFull为true,则表示需要判断所有的关键词,但文本未包含关键词,可直接结束循环
|
||||
if (judgeFull) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//若整个循环结束后,方法仍未结束,则只存在以下两种情况:
|
||||
//1.keyFull为false,且整个循环下来,文本均为包含关键词,则此时返回false
|
||||
//2.keyFull为true,且整个循环下来,文本均包含关键词,则此时返回true
|
||||
//根据以上结果,可以得出,循环结束后仍未结束方法的,则可以直接返回keyFull
|
||||
return judgeFull;
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>GroupNotFindException.java</p>
|
||||
* <p><b>用途:</b>当条件组名不存在时抛出的异常</p>
|
||||
* <p><b>编码时间:</b>2020年1月9日上午8:57:41</p>
|
||||
* <p><b>修改时间:</b>2020年1月9日上午8:57:41</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class GroupNotFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public GroupNotFoundException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GroupNotFoundException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public GroupNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public GroupNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public GroupNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Condition.java</p>
|
||||
* <p><b>用途:</b>该类用于对文本的筛选条件进行编辑,可编辑的条件包含字符串、时间及数字</p>
|
||||
* <p><b>编码时间:</b>2020年1月2日上午7:48:53</p>
|
||||
* <p><b>修改时间:</b>2020年1月2日上午7:48:53</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class Logic {
|
||||
/**
|
||||
* 用于标记对信息的分隔
|
||||
*/
|
||||
private final String GROUP_SIGN = "group=";
|
||||
|
||||
/**
|
||||
* 表示逻辑的入口
|
||||
*/
|
||||
private String mainGroup = "";
|
||||
|
||||
/**
|
||||
* 存储条件组
|
||||
*/
|
||||
private HashMap<String, ConditionGroup> conditionGroupMap = new HashMap<>(16);
|
||||
|
||||
/**
|
||||
* 初始化一个条件组,以作为整个逻辑的开始
|
||||
* @param conditionGroupName 条件组名称
|
||||
* @param condition 条件类对象
|
||||
* @param not 是否对条件取反
|
||||
*/
|
||||
public Logic(String conditionGroupName, Condition<?> condition, boolean not) {
|
||||
//定义条件组,并加上根条件
|
||||
conditionGroupMap.put(conditionGroupName, new ConditionGroup(condition, not));
|
||||
//将逻辑类的入口定义为相应的条件组
|
||||
mainGroup = GROUP_SIGN + conditionGroupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向逻辑中添加一个条件组,并向条件组中添加一个根条件
|
||||
* @param groupName 条件组名称
|
||||
* @param condition 条件类对象
|
||||
*/
|
||||
public void addGroup(String groupName, Condition<?> condition) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回条件组,可通过该方法对条件组进行增减条件的操作
|
||||
* @param GroupName 条件组名称
|
||||
* @return 条件组类
|
||||
* @throws GroupNotFoundException 条件组不存在时抛出的异常
|
||||
*/
|
||||
public ConditionGroup getGroup(String groupName) {
|
||||
if (!conditionGroupMap.containsKey(groupName)) {
|
||||
throw new GroupNotFoundException("不存在的条件组:" + groupName);
|
||||
}
|
||||
|
||||
return conditionGroupMap.get(groupName);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p><b> 文件名:</b>Logic.java</p>
|
||||
* <p><b>用途:</b>用于存放条件的组合,包含对条件的增删改查的操作</p>
|
||||
* <p><b>编码时间:</b>2020年1月9日上午7:49:37</p>
|
||||
* <p><b>修改时间:</b>2020年1月9日上午7:49:37</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
class ConditionGroup {
|
||||
/**
|
||||
* 用于对条件进行取反的标记
|
||||
*/
|
||||
private final String NOT = "-";
|
||||
|
||||
/**
|
||||
* 存储条件,使用字符串进行存储,其条件类返回的条件也必须是字符串
|
||||
*/
|
||||
private ArrayList<String> conditions = new ArrayList<>();
|
||||
/**
|
||||
* 存储条件间的关系
|
||||
*/
|
||||
private ArrayList<RelationType> relations = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 构造条件组,并向其中添加条件,该条件作为逻辑组的根条件使用
|
||||
* @param condition 条件类对象
|
||||
* @param not 是否对条件取反
|
||||
*/
|
||||
public ConditionGroup(Condition<?> condition, boolean not) {
|
||||
//判断是否需要对条件进行取反
|
||||
if (not) {
|
||||
conditions.add(NOT + condition.toString());
|
||||
} else {
|
||||
conditions.add(condition.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造条件组,并向其中添加另一组条件组,该条件组作为逻辑组的根条件使用
|
||||
* @param condition 条件类对象
|
||||
* @param not 是否对条件取反
|
||||
*/
|
||||
public ConditionGroup(String groupName, boolean not) {
|
||||
//判断条件组是否存在
|
||||
if (!conditionGroupMap.containsKey(groupName)) {
|
||||
throw new GroupNotFoundException("不存在的条件组:" + groupName);
|
||||
}
|
||||
|
||||
//添加条件组,并用开始和结束标志来标记条件组名称
|
||||
//判断是否需要对条件进行取反
|
||||
if (not) {
|
||||
//添加条件组,并用开始和结束标志来标记条件组名称
|
||||
conditions.add(NOT + GROUP_SIGN + groupName);
|
||||
} else {
|
||||
conditions.add(GROUP_SIGN + groupName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 向条件组中添加正条件,即数据根据条件得到的结果无需取反
|
||||
* @param condition 条件类对象
|
||||
* @param relationType 与前一个条件间的关系,见{@link RelationType}枚举类
|
||||
* @param not 是否对条件取反
|
||||
*/
|
||||
public void addCondition(Condition<?> condition, RelationType relationType, boolean not) {
|
||||
//判断是否需要对条件进行取反
|
||||
if (not) {
|
||||
conditions.add(NOT + condition.toString());
|
||||
} else {
|
||||
conditions.add(condition.toString());
|
||||
}
|
||||
|
||||
relations.add(relationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向条件组中添加另一个正条件组,即数据根据条件得到的结果无需取反
|
||||
* @param groupName 条件组名称
|
||||
* @param relationType 与前一个条件间的关系,见{@link RelationType}枚举类
|
||||
* @param not 是否对条件取反
|
||||
*/
|
||||
public void addConditionGroup(String groupName, RelationType relationType, boolean not) {
|
||||
//判断条件组是否存在
|
||||
if (!conditionGroupMap.containsKey(groupName)) {
|
||||
throw new GroupNotFoundException("不存在的条件组:" + groupName);
|
||||
}
|
||||
|
||||
//判断是否需要对条件进行取反
|
||||
if (not) {
|
||||
//添加条件组,并用开始和结束标志来标记条件组名称
|
||||
conditions.add(NOT + GROUP_SIGN + groupName);
|
||||
} else {
|
||||
conditions.add(GROUP_SIGN + groupName);
|
||||
}
|
||||
relations.add(relationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据条件的索引值,对添加在条件组中的条件进行删除,条件在条件组中的索引值为添加条件的顺序。
|
||||
* 该方法亦可以删除根条件,删除根条件后,其下一个条件将作为根条件,并删除其与之前的根节点的条件,
|
||||
* 删除普通条件时,将删除被删除的条件与上一个条件的逻辑关系。
|
||||
* </p>
|
||||
* <p>
|
||||
* 例如:存在逻辑“p∧q∨a”(p、q、a均为条件,p为根条件)
|
||||
* <ul>
|
||||
* <li>删除条件p时,则逻辑变为:“q∨a”</li>
|
||||
* <li>删除条件q时,则逻辑变为:“p∨a”</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param index 条件索引值
|
||||
*/
|
||||
public void deleteCondition(int index) {
|
||||
// conditions.remove(index);
|
||||
//删除分为两种情况:
|
||||
//1.删除根条件,则连同删除与下一个条件间的逻辑关系
|
||||
//2.删除普通条件,则连同删除与上一个条件间的逻辑关系
|
||||
|
||||
//先删除条件,若传入的下标有误,则可以先抛出异常,而不会删除关系
|
||||
conditions.remove(index);
|
||||
//判断删除的条件是否为根条件
|
||||
if (index == 0) {
|
||||
relations.remove(0);
|
||||
} else {
|
||||
//根据存储机制,被删除的节点与上一个节点的关系将为相应的下标 - 1(根节点除外)
|
||||
relations.remove(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空条件组
|
||||
*/
|
||||
public void clearCondition() {
|
||||
//清空条件集合及关系集合
|
||||
conditions.clear();
|
||||
relations.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于清除一类所有的条件,例如,清空所有对字符串处理的条件
|
||||
*/
|
||||
public void deleteConditionClass() {
|
||||
//TODO 条件类返回结果定下后再确定该位置的写法
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回条件集合
|
||||
* @return 条件集合
|
||||
*/
|
||||
public ArrayList<String> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回关系集合
|
||||
* @return 关系集合
|
||||
*/
|
||||
public ArrayList<RelationType> getRelations() {
|
||||
return relations;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
public class NumberCondition extends Condition<NumberCondition> {
|
||||
@Override
|
||||
public boolean judgeData(String data, NumberCondition condition) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Relation.java</p>
|
||||
* <p><b>用途:</b>定义添加条件间关系的枚举类,包括“或”(OR)与“且”(AND)</p>
|
||||
* <p><b>编码时间:</b>2020年1月2日上午8:18:09</p>
|
||||
* <p><b>修改时间:</b>2020年1月2日上午8:18:09</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public enum RelationType {
|
||||
OR, AND;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package pres.auxiliary.tool.data;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>RootConditionNotFindException.java</p>
|
||||
* <p><b>用途:</b>当条件组未添加根条件时抛出的异常</p>
|
||||
* <p><b>编码时间:</b>2020年1月8日下午8:45:15</p>
|
||||
* <p><b>修改时间:</b>2020年1月8日下午8:45:15</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class RootConditionNotFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RootConditionNotFoundException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public RootConditionNotFoundException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public RootConditionNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public RootConditionNotFoundException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public RootConditionNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
|
@ -4,8 +4,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import pres.auxiliary.tool.controller.ReadFile;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>DisposeFile.java</p>
|
||||
* <p><b>用途:</b>用于满足日常中对文本文件的处理</p>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.controller;
|
||||
package pres.auxiliary.tool.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
|
@ -1,5 +0,0 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
|
||||
public enum IdCardType {
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
/**
|
||||
* 该枚举定义了部分车牌的样式
|
|
@ -0,0 +1,5 @@
|
|||
package pres.auxiliary.tool.string;
|
||||
|
||||
public enum IdCardType {
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
public class IllegalStringLengthException extends RuntimeException {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
/**
|
||||
* 该枚举用于表示电话号码的类型
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
import java.util.Random;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
public enum RegionType {
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
package pres.auxiliary.tool.randomstring;
|
||||
package pres.auxiliary.tool.string;
|
||||
|
||||
/**
|
||||
* 该枚举规定了产生随机字符串时所需要的模型
|
|
@ -1,77 +0,0 @@
|
|||
package pres.auxiliary.tool.ui.control;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
/**
|
||||
* 实现自动编号的JTextArea控件,编号的方式为“数字.”,如“1.”,每次按下回车键即在下一行自动编号,每次清空所有的文本时则
|
||||
* 自动加上“1.”
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
public class AutoNumberJTextArea extends JTextArea {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 设置初始的编号及键盘监听事件,以实现自动编号
|
||||
*/
|
||||
public AutoNumberJTextArea() {
|
||||
setText("1.");
|
||||
//内部直接实现键盘监听事件
|
||||
addKeyListener(new AutoNumberJTextAreaKeyListener());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造自动编号的键盘监听事件类
|
||||
* @author 彭宇琦
|
||||
*/
|
||||
private class AutoNumberJTextAreaKeyListener implements KeyListener {
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
//判断用户是否按下回车,按下回车后则存储当前文本域中的内容,并添加编号
|
||||
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
|
||||
sb.delete(0, sb.length());
|
||||
sb.append(getText());
|
||||
sb.append("\n");
|
||||
sb.append(getNumber());
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
//判断用户释放的按钮
|
||||
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
|
||||
//若释放回车,则清空文本域中的内容,并将sb中的内容放入文本域中
|
||||
setText("");
|
||||
setText(sb.toString());
|
||||
} else if ( e.getKeyCode() == KeyEvent.VK_BACK_SPACE ) {
|
||||
//若按下的是退格,则判断文本域中的内容是否被清空,若被清空则添加编号“1.”
|
||||
if ( getText().equals("") ) {
|
||||
setText("1.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于判断文本当前的段落数,根据段落数返回当前行所对应的编号
|
||||
* @return 段落所对应的编号数字
|
||||
*/
|
||||
private int getNumber() {
|
||||
//判断文本是否为空,若为空,则返回2,若不为空则返回当前所在段落的行数
|
||||
if ( sb.equals("") ) {
|
||||
return 2;
|
||||
} else {
|
||||
//存储的字符的
|
||||
return sb.toString().split("\n").length + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,357 +0,0 @@
|
|||
package pres.auxiliary.tool.ui.control;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.plaf.basic.ComboPopup;
|
||||
import javax.swing.plaf.metal.MetalComboBoxUI;
|
||||
|
||||
/**
|
||||
* 自动过滤下拉框
|
||||
* @author Sun
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings({ "serial", "rawtypes" })
|
||||
public class InputDoSearchComboBox extends JComboBox {
|
||||
|
||||
/**
|
||||
* 显示用模型
|
||||
*/
|
||||
protected static DefaultComboBoxModel showModel = new DefaultComboBoxModel();
|
||||
/**
|
||||
* 正在选择
|
||||
*/
|
||||
private boolean selectingItem;
|
||||
|
||||
/**
|
||||
* 创建一个 <code>JFilterComboBox</code>,
|
||||
* 其项取自现有的 <code>ComboBoxModel</code>。
|
||||
* 由于提供了 <code>ComboBoxModel</code>,
|
||||
* 使用此构造方法创建的组合框不创建默认组合框模型,
|
||||
* 这可能影响插入、移除和添加方法的行为方式。
|
||||
* @param aModel - 提供显示的项列表的 <code>ComboBoxModel</code>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public InputDoSearchComboBox(ComboBoxModel aModel) {
|
||||
super(aModel);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建包含指定数组中的元素的 <code>JFilterComboBox</code>。
|
||||
* 默认情况下,选择数组中的第一项(因而也选择了该项的数据模型)。
|
||||
* @param items - 要插入到组合框的对象数组
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public InputDoSearchComboBox(final Object items[]) {
|
||||
super(items);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建包含指定 <code>Vector</code> 中的元素的 <code>JFilterComboBox</code>。
|
||||
* 默认情况下,选择数组中的第一项(因而也选择了该项的数据模型)。
|
||||
* @param items - 要插入到组合框的向量数组
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public InputDoSearchComboBox(Vector<?> items) {
|
||||
super(items);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建具有默认数据模型的 <code>JFilterComboBox</code>。
|
||||
* 默认的数据模型为空对象列表。使用 <code>addItem</code> 添加项。
|
||||
* 默认情况下,选择数据模型中的第一项。
|
||||
*/
|
||||
public InputDoSearchComboBox() {
|
||||
super();
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
showModel.addListDataListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
setUI(new MetalFilterComboBoxUI());
|
||||
ListCellRenderer renderer = getRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component) renderer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return showModel.getSelectedItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anObject) {
|
||||
Object oldSelection = selectedItemReminder;
|
||||
Object objectToSelect = anObject;
|
||||
if (oldSelection == null || !oldSelection.equals(anObject)) {
|
||||
|
||||
if (anObject != null && !isEditable()) {
|
||||
boolean found = false;
|
||||
for (int i = 0; i < showModel.getSize(); i++) {
|
||||
Object element = showModel.getElementAt(i);
|
||||
if (anObject.equals(element)) {
|
||||
found = true;
|
||||
objectToSelect = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectingItem = true;
|
||||
showModel.setSelectedItem(objectToSelect);
|
||||
selectingItem = false;
|
||||
|
||||
if (selectedItemReminder != showModel.getSelectedItem()) {
|
||||
selectedItemChanged();
|
||||
}
|
||||
}
|
||||
fireActionEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedIndex(int anIndex) {
|
||||
int size = showModel.getSize();
|
||||
if (anIndex == -1 || size == 0) {
|
||||
setSelectedItem(null);
|
||||
} else if (anIndex < -1) {
|
||||
throw new IllegalArgumentException("setSelectedIndex: " + anIndex
|
||||
+ " out of bounds");
|
||||
} else if (anIndex >= size) {
|
||||
setSelectedItem(showModel.getElementAt(size - 1));
|
||||
} else {
|
||||
setSelectedItem(showModel.getElementAt(anIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectedIndex() {
|
||||
Object sObject = showModel.getSelectedItem();
|
||||
int i, c;
|
||||
Object obj;
|
||||
|
||||
for (i = 0, c = showModel.getSize(); i < c; i++) {
|
||||
obj = showModel.getElementAt(i);
|
||||
if (obj != null && obj.equals(sObject)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
Object oldSelection = selectedItemReminder;
|
||||
Object newSelection = showModel.getSelectedItem();
|
||||
if (oldSelection == null || !oldSelection.equals(newSelection)) {
|
||||
selectedItemChanged();
|
||||
if (!selectingItem) {
|
||||
fireActionEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void selectedItemChanged() {
|
||||
if (selectedItemReminder != null) {
|
||||
fireItemStateChanged(new ItemEvent(this,
|
||||
ItemEvent.ITEM_STATE_CHANGED, selectedItemReminder,
|
||||
ItemEvent.DESELECTED));
|
||||
}
|
||||
|
||||
selectedItemReminder = showModel.getSelectedItem();
|
||||
|
||||
if (selectedItemReminder != null) {
|
||||
fireItemStateChanged(new ItemEvent(this,
|
||||
ItemEvent.ITEM_STATE_CHANGED, selectedItemReminder,
|
||||
ItemEvent.SELECTED));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
if (selectedItemReminder != showModel.getSelectedItem()) {
|
||||
selectedItemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditable(boolean aFlag) {
|
||||
super.setEditable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回显示用模型
|
||||
* @return
|
||||
*/
|
||||
public DefaultComboBoxModel getShowModel() {
|
||||
return showModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metal L&F 风格的 UI 类
|
||||
* @author Sun
|
||||
*
|
||||
*/
|
||||
class MetalFilterComboBoxUI extends MetalComboBoxUI {
|
||||
|
||||
/**
|
||||
* 编辑区事件监听器
|
||||
*/
|
||||
protected EditorListener editorListener;
|
||||
/**
|
||||
* 该 UI 类负责绘制的控件
|
||||
*/
|
||||
protected InputDoSearchComboBox filterComboBox;
|
||||
|
||||
@Override
|
||||
public void installUI(JComponent c) {
|
||||
filterComboBox = (InputDoSearchComboBox) c;
|
||||
filterComboBox.setEditable(true);
|
||||
super.installUI(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureEditor() {
|
||||
super.configureEditor();
|
||||
editor.addKeyListener(getEditorListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unconfigureEditor() {
|
||||
super.unconfigureEditor();
|
||||
if (editorListener != null) {
|
||||
editor.removeKeyListener(editorListener);
|
||||
editorListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComboPopup createPopup() {
|
||||
return new FilterComboPopup(filterComboBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化并返回编辑区事件监听器
|
||||
* @return
|
||||
*/
|
||||
protected EditorListener getEditorListener() {
|
||||
if (editorListener == null) {
|
||||
editorListener = new EditorListener();
|
||||
}
|
||||
return editorListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按关键字进行查询,该方法中,可以自行加入各种查询算法
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void findMatchs() {
|
||||
ComboBoxModel model = filterComboBox.getModel();
|
||||
DefaultComboBoxModel showModel = filterComboBox.getShowModel();
|
||||
showModel.removeAllElements();
|
||||
for (int i = 0; i < model.getSize(); i++) {
|
||||
String name = model.getElementAt(i).toString();
|
||||
if (name.indexOf(getEditorText()) >= 0) {
|
||||
showModel.addElement(model.getElementAt(i));
|
||||
}
|
||||
}
|
||||
((FilterComboPopup)popup ).repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回编辑区文本
|
||||
* @return
|
||||
*/
|
||||
private String getEditorText() {
|
||||
return filterComboBox.getEditor().getItem().toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 弹出面板类
|
||||
* @author Sun
|
||||
*
|
||||
*/
|
||||
class FilterComboPopup extends BasicComboPopup {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public FilterComboPopup(JComboBox combo) {
|
||||
super(combo);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected JList createList() {
|
||||
JList list = super.createList();
|
||||
list.setModel(filterComboBox.getShowModel());
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
if (!b) {
|
||||
comboBox.getEditor().setItem(comboBox.getSelectedItem());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
findMatchs();
|
||||
super.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑区事件监听器类
|
||||
* @author Sun
|
||||
*
|
||||
*/
|
||||
class EditorListener implements KeyListener {
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
findMatchs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
findMatchs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 键入值时调用该方法
|
||||
*/
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
findMatchs();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package pres.auxiliary.work.selenium.datadriven;
|
||||
|
||||
import pres.auxiliary.tool.date.Time;
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Functions.java</p>
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.element;
|
||||
|
||||
public class NoSuchWindownException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NoSuchWindownException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NoSuchWindownException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
|
||||
super(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
public NoSuchWindownException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
}
|
||||
|
||||
public NoSuchWindownException(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
public NoSuchWindownException(Throwable arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -100,12 +100,6 @@ public class AssertEvent extends AbstractEvent {
|
|||
* @throws NoSuchElementException 元素不存在或下标不正确时抛出的异常
|
||||
*/
|
||||
public boolean assertTextContainKey(Element element, boolean isJudgeAllKey, String... keys) {
|
||||
//判断是否传入关键词
|
||||
// boolean result = true;
|
||||
// if (keys != null && keys.length != 0) {
|
||||
// result = judgetText(textEvent.getText(element), isJudgeAllKey, false, keys);
|
||||
// }
|
||||
|
||||
boolean result = assertTextContainKey(element, (e) -> textEvent.getText(e),
|
||||
isJudgeAllKey, keys);
|
||||
|
||||
|
@ -327,7 +321,6 @@ public class AssertEvent extends AbstractEvent {
|
|||
//判断是否传入关键词
|
||||
text = text == null ? "" : text;
|
||||
|
||||
// boolean result = judgetText(textEvent.getText(element), true, true, text);
|
||||
boolean result = assertTextNotContainKey(element, true, text);
|
||||
|
||||
logText = "断言“" + element.getElementData().getName() + "”元素的文本内容不为“" + text + "”";
|
||||
|
@ -336,6 +329,44 @@ public class AssertEvent extends AbstractEvent {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言两个元素内文本一致
|
||||
* @param referencedElement 参考元素
|
||||
* @param comparativeElement 比较元素
|
||||
* @return 断言结果
|
||||
*
|
||||
* @throws TimeoutException 元素无法操作时抛出的异常
|
||||
* @throws NoSuchElementException 元素不存在或下标不正确时抛出的异常
|
||||
*/
|
||||
public boolean assertEqualsElementText(Element referencedElement, Element comparativeElement) {
|
||||
boolean result = assertTextContainKey(referencedElement, true, textEvent.getText(comparativeElement));
|
||||
|
||||
logText = "断言“" + referencedElement.getElementData().getName() + "”元素的文本内容与“"
|
||||
+ comparativeElement + "”元素的文本内容一致";
|
||||
resultText = String.valueOf(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言两个元素内文本不一致
|
||||
* @param referencedElement 参考元素
|
||||
* @param comparativeElement 比较元素
|
||||
* @return 断言结果
|
||||
*
|
||||
* @throws TimeoutException 元素无法操作时抛出的异常
|
||||
* @throws NoSuchElementException 元素不存在或下标不正确时抛出的异常
|
||||
*/
|
||||
public boolean assertNotEqualsElementText(Element referencedElement, Element comparativeElement) {
|
||||
boolean result = assertTextNotContainKey(referencedElement, true, textEvent.getText(comparativeElement));
|
||||
|
||||
logText = "断言“" + referencedElement.getElementData().getName() + "”元素的文本内容与“"
|
||||
+ comparativeElement + "”元素的文本内容不一致";
|
||||
resultText = String.valueOf(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言元素存在
|
||||
* @param element {@link Element}对象
|
||||
|
@ -364,12 +395,30 @@ public class AssertEvent extends AbstractEvent {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言两元素中的数字内容,按照{@link CompareNumberType}指定的比较类型进行比较。若断言的
|
||||
* 元素文本内容存在非数字字符时,则直接断言失败
|
||||
* @param referencedElement 参考元素
|
||||
* @param compareNumberType 比较方式{@link CompareNumberType}枚举类
|
||||
* @param comparativeElement 比较元素
|
||||
* @return 断言结果
|
||||
*/
|
||||
public boolean assertElementsNumber(Element referencedElement, CompareNumberType compareNumberType, Element comparativeElement) {
|
||||
logText = "断言“" + referencedElement.getElementData().getName() + "”元素数字内容"
|
||||
+ compareNumberType.getLogText()
|
||||
+ "“" + comparativeElement.getElementData().getName() + "”元素数字内容";
|
||||
boolean result = assertNumber(referencedElement, compareNumberType, Double.valueOf(textEvent.getText(comparativeElement)));
|
||||
|
||||
resultText = String.valueOf(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言元素中的数字内容与指定的数字按照{@link CompareNumberType}指定的比较类型进行比较。若断言的
|
||||
* 元素文本内容为非数字字符时,则直接断言失败
|
||||
*
|
||||
* @param element {@link Element}对象
|
||||
* @param compareNumberType {@link CompareNumberType}枚举类
|
||||
* @param compareNumberType 比较方式{@link CompareNumberType}枚举类
|
||||
* @param compareNumber 预期数字
|
||||
* @return 断言结果
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
package pres.auxiliary.work.selenium.event.extend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.openqa.selenium.Keys;
|
||||
|
||||
import pres.auxiliary.work.selenium.brower.AbstractBrower;
|
||||
import pres.auxiliary.work.selenium.element.DataListBy;
|
||||
import pres.auxiliary.work.selenium.element.Element;
|
||||
import pres.auxiliary.work.selenium.event.AbstractEvent;
|
||||
import pres.auxiliary.work.selenium.event.AssertEvent;
|
||||
import pres.auxiliary.work.selenium.event.ClickEvent;
|
||||
import pres.auxiliary.work.selenium.event.TextEvent;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>OperateDataTable.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 提供对数据表格进行基本操作的事件,包括对数据列表的翻页、跳页、获取等操作,以简化部分操作的代码
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年11月17日上午7:58:40</p>
|
||||
* <p><b>修改时间:</b>2020年11月17日上午7:58:40</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 1.8
|
||||
*
|
||||
*/
|
||||
public class DataTableEvent extends AbstractEvent {
|
||||
/**
|
||||
* 用于进行点击事件
|
||||
*/
|
||||
private ClickEvent clickEvent;
|
||||
/**
|
||||
* 用于进行文本事件
|
||||
*/
|
||||
private TextEvent textEvent;
|
||||
/**
|
||||
* 用于进行断言事件
|
||||
*/
|
||||
private AssertEvent assertEvent;
|
||||
|
||||
/**
|
||||
* 用于存储当前的列表元素
|
||||
*/
|
||||
protected ArrayList<DataListBy> tableList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 用于存储当前列表的长度
|
||||
*/
|
||||
protected int listSize = -1;
|
||||
|
||||
/**
|
||||
* 标记是否进行元素个数长度校验
|
||||
*/
|
||||
protected boolean isExamine = true;
|
||||
|
||||
/**
|
||||
* 构造对象
|
||||
*
|
||||
* @param brower 浏览器{@link AbstractBrower}类对象
|
||||
*/
|
||||
public DataTableEvent(AbstractBrower brower) {
|
||||
super(brower);
|
||||
|
||||
clickEvent = new ClickEvent(brower);
|
||||
textEvent = new TextEvent(brower);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于设置是否对传入的元素列表的个数进行严格校验,即在调用{@link #add(DataListBy)}方法时,
|
||||
* 若元素个数与初次传入的个数不符且需要严格校验,则抛出异常;反之,则直接进行存储
|
||||
* @param isExamine 是否严格校验元素个数
|
||||
*/
|
||||
public void setExamine(boolean isExamine) {
|
||||
this.isExamine = isExamine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于添加一列元素,调用该方法时将对存储的
|
||||
* @param dataListBy 元素列查找对象
|
||||
*/
|
||||
public void add(DataListBy dataListBy) {
|
||||
//判断当前是否存储元素,若未存储元素,则不进行元素个数判断
|
||||
if (!tableList.isEmpty()) {
|
||||
//判断传入的列的元素个数是否与当前存储的元素个数一致,若不一致,则进行个数判定校验
|
||||
int nowSize = dataListBy.size();
|
||||
if (nowSize != size()) {
|
||||
//若当前需要严格校验列表元素个数,则抛出异常
|
||||
if (isExamine) {
|
||||
throw new InvalidDataListException("当前传入的元素列个数与存储的元素列个数不一致!"
|
||||
+ "(当前元素列个数:" + size() + ",传入的元素列元素个数:" + nowSize + ")");
|
||||
} else {
|
||||
//若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字
|
||||
listSize = listSize < nowSize ? listSize : nowSize;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
listSize = dataListBy.size();
|
||||
}
|
||||
|
||||
tableList.add(dataListBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回元素列中元素的个数,若设置了严格判断,则该数值为所有列的元素个数;反之,则该
|
||||
* 数值表示列表集合中,最短元素列的元素个数
|
||||
*
|
||||
* @return 元素列的元素个数
|
||||
*/
|
||||
public int size() {
|
||||
return listSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于点击一次上一页按钮,并返回点击成功结果
|
||||
* @param upPageButton 上一页按钮元素
|
||||
* @return 点击结果
|
||||
*/
|
||||
public boolean upPage(Element upPageButton) {
|
||||
boolean result = operateSuchAssertData(() -> {
|
||||
//判断按钮是否可以点击
|
||||
if (!upPageButton.getWebElement().isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
clickEvent.click(upPageButton);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
logText = "点击“" + upPageButton.getElementData().getName() + "”元素,返回列表上一页,其翻页"
|
||||
+ (result ? "" : "不") + "成功";
|
||||
resultText = String.valueOf(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数)
|
||||
* @param upPageButton 上一页按钮元素
|
||||
* @param count 点击次数
|
||||
* @return 实际点击次数
|
||||
*/
|
||||
public int upPage(Element upPageButton, int count) {
|
||||
int nowCount = 0;
|
||||
//根据设置的点击次数循环点击上一页
|
||||
while (nowCount < count) {
|
||||
//若点击成功,则nowCount自增,若点击失败,则退出循环
|
||||
if (upPage(upPageButton)) {
|
||||
nowCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logText = "连续点击“" + upPageButton.getElementData().getName() + "”元素,使列表返回至上"
|
||||
+ count + "页,其实际翻页数为:" + nowCount;
|
||||
resultText = String.valueOf(nowCount);
|
||||
|
||||
//返回实际点击次数
|
||||
return nowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于持续点击上一页按钮,直到按钮不可点击为止,并返回实际点击次数(实际点击次数)
|
||||
* @param upPageButton 上一页按钮元素
|
||||
* @return 实际点击次数
|
||||
*/
|
||||
public int continueUpPage(Element upPageButton) {
|
||||
int nowCount = 0;
|
||||
//根据设置的点击次数循环点击上一页
|
||||
while (true) {
|
||||
//若点击成功,则nowCount自增,若点击失败,则退出循环
|
||||
if (upPage(upPageButton)) {
|
||||
nowCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logText = "持续点击“" + upPageButton.getElementData().getName() + "”元素,使列表返回至首页"
|
||||
+ ",其实际翻页数为:" + nowCount;
|
||||
resultText = String.valueOf(nowCount);
|
||||
|
||||
//返回实际点击次数
|
||||
return nowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对列表进行点击跳页按钮后的跳页操作。若当前存储过元素列表,则对元素列表进行断言,
|
||||
* 即取存储的列表的第一行元素,若操作前后,该行元素不变,则判定为跳页失败
|
||||
*
|
||||
* @param pageTextbox 跳页文本框元素
|
||||
* @param jumpPageButton 跳页按钮
|
||||
* @param pageCountText 页码文本
|
||||
*/
|
||||
public boolean jumpPage(Element pageTextbox, Element jumpPageButton, String pageCount) {
|
||||
boolean result = operateSuchAssertData(() -> {
|
||||
//输入页码
|
||||
textEvent.input(pageTextbox, pageCount);
|
||||
//点击跳页
|
||||
clickEvent.click(jumpPageButton);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
logText = "在“" + pageTextbox.getElementData().getName() + "”元素中输入" + pageCount
|
||||
+ ",点击“ + jumpPageButton.getElementData().getName() + ”按钮,跳到列表相应的页码,其翻页"
|
||||
+ (result ? "" : "不") + "成功";
|
||||
resultText = String.valueOf(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对列表按下回车后的跳页操作。若当前存储过元素列表,则对元素列表进行断言,
|
||||
* 即取存储的列表的第一行元素,若操作前后,该行元素不变,则判定为跳页失败
|
||||
*
|
||||
* @param pageTextbox 跳页文本框元素
|
||||
* @param pageCountText 页码文本
|
||||
*/
|
||||
public boolean jumpPage(Element pageTextbox, String pageCount) {
|
||||
boolean result = operateSuchAssertData(() -> {
|
||||
//输入页码
|
||||
textEvent.input(pageTextbox, pageCount);
|
||||
//点击跳页
|
||||
textEvent.keyToSend(pageTextbox, Keys.ENTER);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
logText = "在“" + pageTextbox.getElementData().getName() + "”元素中输入" + pageCount
|
||||
+ ",按下回车,跳到列表相应的页码,其翻页"
|
||||
+ (result ? "" : "不") + "成功";
|
||||
resultText = String.valueOf(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 获取指定的一行元素,下标允许传入负数,表示从后向前遍历,具体遍历逻辑
|
||||
* 可参考{@link DataListBy#getElement(int)}方法。
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>注意:</b>下标将按照元素列长度进行计算,若下标的绝对值大于元素列长度,且下标为正数,则
|
||||
* 获取最后一行元素;反之,则获取第一行元素。元素列个数可参考{@link #size()}方法
|
||||
* </p>
|
||||
*
|
||||
* @param rowIndex 需要获取的行下标
|
||||
* @return 指定行的元素集合
|
||||
*/
|
||||
public ArrayList<Element> getRowElement(int rowIndex) {
|
||||
//根据下标,获取元素,并进行存储
|
||||
ArrayList<Element> elementList = new ArrayList<>();
|
||||
IntStream.range(0, tableList.size()).forEach(index -> {
|
||||
elementList.add(tableList.get(index).getElement(rowIndex));
|
||||
});
|
||||
|
||||
return elementList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言数据是否有改变,若数据改变,则返回true;反之,返回false
|
||||
* @param oldElementList 原始数据元素列表
|
||||
* @param newElementList 新数据元素列表
|
||||
* @return 元素是否存在改变
|
||||
*/
|
||||
protected boolean assertDataChange(ArrayList<Element> oldElementList, ArrayList<Element> newElementList) {
|
||||
//获取两数组的长度
|
||||
int oldSize = oldElementList.size();
|
||||
int newSize = newElementList.size();
|
||||
|
||||
//若两数组长度不一致,说明元素有改变,则返回true
|
||||
if (oldSize != newSize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//若列表第一个元素与新列表第一个元素相同,说明列表并未改变,则返回false
|
||||
if (!oldElementList.get(0).equals(newElementList.get(0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//为避免不进行翻页时,列表也会进行一次刷新,则获取信息,对每个文本数据进行比对
|
||||
for (int index = 0; index < oldSize; index++) {
|
||||
if (assertEvent.assertNotEqualsElementText(oldElementList.get(index), newElementList.get(index))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 由于方法允许传入负数和特殊数字0为下标,并且下标的序号由1开始,
|
||||
* 故可通过该方法对下标的含义进行转义,得到java能识别的下标
|
||||
*
|
||||
* @param length 元素的个数
|
||||
* @param index 传入的下标
|
||||
* @return 可识别的下标
|
||||
*/
|
||||
protected int toElementIndex(int length, int index) {
|
||||
// 判断元素下标是否超出范围,由于可以传入负数,故需要使用绝对值
|
||||
if (Math.abs(index) > length) {
|
||||
if (index > 0) {
|
||||
return length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断index的值,若大于0,则从前向后遍历,若小于0,则从后往前遍历,若等于0,则随机输入
|
||||
if (index > 0) {
|
||||
// 选择元素,正数的选项值从1开始,故需要减小1
|
||||
return index - 1;
|
||||
} else if (index < 0) {
|
||||
// 选择元素,由于index为负数,则长度加上选项值即可得到需要选择的选项
|
||||
return length + index;
|
||||
} else {
|
||||
return new Random().nextInt(length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于执行需要断言页面元素的列表操作,在其操作方法前后添加了断言操作
|
||||
* @param action 需要执行的内容
|
||||
* @return 是否翻页成功
|
||||
*/
|
||||
private boolean operateSuchAssertData(BooleanSupplier action) {
|
||||
//若元素列表非空,则获取第一行元素,用于进行断言
|
||||
ArrayList<Element> oldElementList = new ArrayList<>();
|
||||
if (!tableList.isEmpty()) {
|
||||
//获取第一行元素
|
||||
oldElementList = getRowElement(1);
|
||||
}
|
||||
|
||||
//执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作
|
||||
if (action.getAsBoolean()) {
|
||||
//获取操作后的第一行元素
|
||||
ArrayList<Element> newElementList = new ArrayList<>();
|
||||
if (!tableList.isEmpty()) {
|
||||
//获取第一行元素
|
||||
newElementList = getRowElement(1);
|
||||
}
|
||||
|
||||
//断言元素,并返回结果
|
||||
return assertDataChange(oldElementList, newElementList);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>DataTableEvent.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 若元素列表无法添加时抛出的异常
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年11月19日下午8:26:49</p>
|
||||
* <p><b>修改时间:</b>2020年11月19日下午8:26:49</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 1.8
|
||||
*
|
||||
*/
|
||||
public class InvalidDataListException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidDataListException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidDataListException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public InvalidDataListException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidDataListException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidDataListException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.tool;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>Log.java</p>
|
||||
* <p><b>用途:</b>用于在txt文件中生成自动化测试相关的日志,亦可指定输出的内容</p>
|
||||
* <p><b>编码时间:</b>2019年6月1日上午11:34:54</p>
|
||||
* <p><b>修改时间:</b>2019年10月6日下午6:03:39</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*/
|
||||
public class Log_Old {
|
||||
/**
|
||||
* 用于存储文件的保存路径
|
||||
*/
|
||||
private StringBuilder savePath = new StringBuilder("C:\\AutoTest\\Log\\");
|
||||
/**
|
||||
* 用于存储的文件名称
|
||||
*/
|
||||
private StringBuilder fileName = new StringBuilder("TestResults");
|
||||
|
||||
/**
|
||||
* 用于存储当前正在运行的类名
|
||||
*/
|
||||
private String className = "";
|
||||
|
||||
/**
|
||||
* 用于存储当前正在运行的测试方法名
|
||||
*/
|
||||
private String methodName = "";
|
||||
|
||||
/**
|
||||
* 用于标识是否已经开始进行了记录
|
||||
*/
|
||||
private boolean startRecord = false;
|
||||
|
||||
/**
|
||||
* 用于按默认方式建文件保存位置及文件名称<br/>
|
||||
* 默认位置为:C:\\AutoTestting\\TestResults\\<br/>
|
||||
* 默认文件名为(不带后缀):TestResults
|
||||
*/
|
||||
public Log_Old() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于按指定的路径以及默认的文件名保存测试结果文件<br/>
|
||||
* 默认文件名为(不带后缀):Image<br/>
|
||||
* 注意,传入的文件路径可为相对路径,也可为绝对路径,若路径不符合windows下文件夹名称的名称规则,
|
||||
* 则抛出IncorrectDirectoryException异常
|
||||
*
|
||||
* @param savePath
|
||||
* 指定的测试结果文件保存路径
|
||||
* @throws IncorrectDirectoryException
|
||||
* 传入路径不合法时抛出的异常
|
||||
*/
|
||||
public Log_Old(String savePath) {
|
||||
setSavePath(savePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于按指定的路径以及指定的文件名保存测试结果文件
|
||||
*
|
||||
* @param savePath
|
||||
* 指定的测试结果文件保存路径
|
||||
* @param imageName
|
||||
* 指定的测试结果文件文件名
|
||||
* @throws IncorrectDirectoryException
|
||||
* 传入的路径不合法或者文件名不合法时抛出的异常
|
||||
*/
|
||||
public Log_Old(String savePath, String fileName) {
|
||||
setSavePath(savePath);
|
||||
setFileName(fileName);
|
||||
}
|
||||
|
||||
public String getSavePath() {
|
||||
return savePath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于设置测试结果文件保存的位置,可传入相对路径,也可传入绝对路径,
|
||||
* 若传入的路径不符合windows下文件夹名称的命名规则时,则抛出IncorrectDirectoryException异常
|
||||
*
|
||||
* @param savePath
|
||||
* 传入的测试结果文件保存路径
|
||||
* @throws IncorrectDirectoryException
|
||||
* 传入路径不合法时抛出的异常
|
||||
*/
|
||||
public void setSavePath(String savePath) {
|
||||
// 将传入的路径封装成StringBuilder,以便格式化
|
||||
StringBuilder sb = new StringBuilder(savePath);
|
||||
// 格式化传入的路径
|
||||
MakeDirectory.formatPath(sb);
|
||||
|
||||
// 判断传入的路径是否符合windows下对文件夹名称命名的规则,如果不符合则抛出IncorrectDirectoryException异常
|
||||
if (!MakeDirectory.isPath(sb.toString())) {
|
||||
throw new IncorrectDirectoryException("不合理的文件夹路径,文件路径:" + sb.toString());
|
||||
}
|
||||
|
||||
// 将通过判断的sb赋给savePath属性
|
||||
this.savePath = sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回测试结果文件的文件名称(不含后缀)
|
||||
*
|
||||
* @return 测试结果文件的文件名称
|
||||
*/
|
||||
public String getFileName() {
|
||||
return fileName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于设置测试结果文件的文件名称,若传入的文件名不符合windows下文件的命名规则,
|
||||
* 则抛出IncorrectDirectoryException异常
|
||||
*
|
||||
* @param fileName
|
||||
* 指定的测试结果文件名称
|
||||
* @throws IncorrectDirectoryException
|
||||
* 文件命名不正确时抛出的异常
|
||||
*/
|
||||
public void setFileName(String fileName) {
|
||||
// 判断传入的测试结果文件名称是否符合windows下的命名规则,若不符合,则抛出IncorrectDirectoryException异常
|
||||
if (!MakeDirectory.isFileName(fileName)) {
|
||||
throw new IncorrectDirectoryException("不合理的文件名称,文件名称:" + fileName);
|
||||
}
|
||||
|
||||
// 通过判断后,则清空fileName存储的信息并将新的文件名称放入fileName种属性中
|
||||
this.fileName.delete(0, this.fileName.length());
|
||||
this.fileName.append(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于创建测试结果文件并保存到相应的路径下,通过类中存储的测试结果文件保存路径和测试结果文件文件名来创写入文件。
|
||||
*
|
||||
* @param text
|
||||
* 待写入文件的内容
|
||||
* @throws IOException
|
||||
* 文件流状态不正确时抛出的异常
|
||||
* @throws UndefinedDirectoryException
|
||||
* 测试结果文件保存路径或测试结果文件名称未指定时抛出的异常
|
||||
*/
|
||||
public void write(String text) throws IOException {
|
||||
// 判断text中的内容是否为空,为空则直接返回
|
||||
if (text == null || "".equals(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断测试结果文件保存路径和测试结果文件名是否存在,若不存在则抛出UndefinedDirectoryException异常
|
||||
if ("".equals(savePath.toString()) || "".equals(fileName.toString())) {
|
||||
throw new UndefinedDirectoryException(
|
||||
"未定义文件路径或者文件名,文件路径:" + savePath.toString() + ",文件名:" + fileName.toString());
|
||||
}
|
||||
|
||||
// 调用writeFile()方法,将测试内容写入文件中
|
||||
writeFile(text);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于标识开始进行自动化测试运行记录
|
||||
* @param className 测试类名
|
||||
* @param methodName 测试方法名
|
||||
* @throws IOException 文件流状态不正确时抛出的异常
|
||||
* @throws RecordStateException 未调用结束记录的方法时调用了此方法后抛出的异常
|
||||
*/
|
||||
public void startWrite(String className, String methodName) throws IOException {
|
||||
//当运行状态为true时,说明此次调用前未调用endWrite()方法,则抛出异常
|
||||
if (startRecord) {
|
||||
throw new RecordStateException("当前运行状态为" + startRecord + ",需要调用结束记录的方法再调用该方法");
|
||||
}
|
||||
|
||||
this.className = className;
|
||||
this.methodName = methodName;
|
||||
|
||||
write("正在运行" + className + "类的" + methodName + "()方法");
|
||||
|
||||
startRecord = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于标识结束进行自动化测试运行记录
|
||||
*
|
||||
* @param bugNumber
|
||||
* 指定的BUG数量
|
||||
* @throws IOException
|
||||
* 文件流状态不正确时抛出的异常
|
||||
* @throws RecordStateException
|
||||
* 未调用开始记录的方法时调用了此方法后抛出的异常
|
||||
*/
|
||||
public void endWrite(int bugNumber) throws IOException {
|
||||
if (!startRecord) {
|
||||
throw new RecordStateException("当前运行状态为" + startRecord + ",需要调用开始记录的方法再调用该方法");
|
||||
}
|
||||
|
||||
write(className + "类的" + methodName + "方法运行结束,共发现BUG" + bugNumber + "个");
|
||||
startRecord = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法用于将用户输入的内容写入指定的文件中
|
||||
*
|
||||
* @param text
|
||||
* 指定写入的内容
|
||||
* @throws IOException
|
||||
* 流异常时抛出的异常
|
||||
*/
|
||||
private void writeFile(String text) throws IOException {
|
||||
// 用于存储待写入文件的内容
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
|
||||
// 将savePath中保存的路径作为测试结果文件保存路径创建文件夹
|
||||
new File(savePath.toString()).mkdirs();
|
||||
// 定义文件写入流,设置为不覆盖当前文本
|
||||
FileWriter fw = new FileWriter(new File(getSavePath() + getFileName() + ".txt"), true);
|
||||
|
||||
// 将待写入文件的内容放入sb中
|
||||
sb.append("[");
|
||||
sb.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
sb.append("]");
|
||||
sb.append(text);
|
||||
sb.append("\r\n");
|
||||
|
||||
// 将sb中的内容写入文件
|
||||
fw.write(sb.toString());
|
||||
|
||||
// 刷新文件并关闭流
|
||||
fw.flush();
|
||||
fw.close();
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,38 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.tool;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>RecordToolConfigException.java</p>
|
||||
* <p><b>用途:</b>使用RecordTool类时,其类中使用的工具未配置正确时抛出该异常</p>
|
||||
* <p><b>编码时间:</b>2019年9月22日上午11:48:16</p>
|
||||
* <p><b>修改时间:</b>2019年9月22日上午11:48:16</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class RecordToolConfigException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RecordToolConfigException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RecordToolConfigException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public RecordToolConfigException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RecordToolConfigException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RecordToolConfigException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package pres.auxiliary.work.selenium.tool;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>RunLog.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 以纯文本的形式记录自动化运行过程
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年9月3日上午8:02:37</p>
|
||||
* <p><b>修改时间:</b>2020年9月3日上午8:02:37</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*
|
||||
*/
|
||||
public class RunLog {
|
||||
/**
|
||||
* 指向日志文件类对象
|
||||
*/
|
||||
private File logFile = null;
|
||||
|
||||
public RunLog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造对象,并指定日志存放位置
|
||||
* @param logFile 日志文件类对象
|
||||
*/
|
||||
public RunLog(File logFile) {
|
||||
this.logFile = logFile;
|
||||
}
|
||||
}
|
|
@ -10,8 +10,8 @@ import java.util.Date;
|
|||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
|
||||
public class TimeTest {
|
||||
Time time = new Time();
|
||||
|
|
|
@ -2,6 +2,9 @@ package pres.auxiliary.tool.randomstring;
|
|||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import pres.auxiliary.tool.string.MobleNumberType;
|
||||
import pres.auxiliary.tool.string.PresetString;
|
||||
|
||||
public class PresetStringTest {
|
||||
@Test
|
||||
public void IdentityCardTest() {
|
||||
|
|
|
@ -4,6 +4,9 @@ import org.testng.annotations.AfterMethod;
|
|||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import pres.auxiliary.tool.string.MobleNumberType;
|
||||
import pres.auxiliary.tool.string.RandomWord;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>RandomWordTest.java</p>
|
||||
* <p><b>用途:</b>
|
||||
|
|
|
@ -8,8 +8,8 @@ import org.testng.annotations.AfterMethod;
|
|||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
import pres.auxiliary.work.selenium.datadriven.TestNGDataDriver.Data;
|
||||
|
||||
public class TestNGDataDriverTest {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package test.javase;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
|
||||
public class RandomPhone {
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -2,7 +2,7 @@ package test.javase;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
|
||||
/**
|
||||
* FileName: SweepPlan.java
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
package test.javase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
|
||||
public class TestArrayList {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
int count = 10000000;
|
||||
|
||||
System.out.println("开始添加" + count + "个随机内容");
|
||||
Date start = new Date();
|
||||
for (int i = 0; i < count; i++) {
|
||||
al.add(new RandomString(StringMode.CH).toString(10, 30));
|
||||
}
|
||||
System.out.println("添加完毕,耗时:" + (new Date().getTime() - start.getTime()));
|
||||
System.out.println("随机抽取10个内容");
|
||||
start = new Date();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("第" + (i + 1) + "个内容:" + al.get(new Random().nextInt(10000)));
|
||||
}
|
||||
System.out.println("抽取完毕,耗时:" + (new Date().getTime() - start.getTime()));
|
||||
}
|
||||
|
||||
}
|
||||
package test.javase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
|
||||
public class TestArrayList {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
int count = 10000000;
|
||||
|
||||
System.out.println("开始添加" + count + "个随机内容");
|
||||
Date start = new Date();
|
||||
for (int i = 0; i < count; i++) {
|
||||
al.add(new RandomString(StringMode.CH).toString(10, 30));
|
||||
}
|
||||
System.out.println("添加完毕,耗时:" + (new Date().getTime() - start.getTime()));
|
||||
System.out.println("随机抽取10个内容");
|
||||
start = new Date();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("第" + (i + 1) + "个内容:" + al.get(new Random().nextInt(10000)));
|
||||
}
|
||||
System.out.println("抽取完毕,耗时:" + (new Date().getTime() - start.getTime()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ package test.javase;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
import pres.auxiliary.work.old.testcase.templet.ZentaoTemplet;
|
||||
|
||||
public class TestCase2 {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package test.javase;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.CarLicecenType;
|
||||
import pres.auxiliary.tool.randomstring.PresetString;
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.randomstring.StringMode;
|
||||
import pres.auxiliary.tool.string.CarLicecenType;
|
||||
import pres.auxiliary.tool.string.PresetString;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
import pres.auxiliary.tool.string.StringMode;
|
||||
|
||||
public class TestPresetStr {
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package test.javase;
|
||||
|
||||
import pres.auxiliary.tool.randomstring.RandomString;
|
||||
import pres.auxiliary.tool.string.RandomString;
|
||||
|
||||
public class TestRandomString {
|
||||
public static void main(String[] args) {
|
||||
|
|
Loading…
Reference in New Issue