From a0c8c09c63fe39ee122d80101fc0d09106d46111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Fri, 20 Nov 2020 23:14:32 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8C=85=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E6=B8=85=E7=90=86=E6=8A=A5=E9=94=99=E7=B1=BB?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=88=97=E8=A1=A8=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pres/auxiliary/report/AbstractReport.java | 1810 ----------------- .../pres/auxiliary/report/AutoTestReport.java | 45 - .../auxiliary/report/BugFilePosition.java | 269 --- .../IncompatibleFileLayoutException.java | 38 - .../report/IncorrectBugVersionException.java | 33 - .../report/IncorrectGrammarException.java | 36 - .../InvalidBugListFileSignException.java | 36 - .../pres/auxiliary/report/ReportFactory.java | 45 - .../pres/auxiliary/report/ReportInter.java | 118 -- .../pres/auxiliary/report/TestReport.java | 1073 ---------- .../auxiliary/report/ui/SandMailFrame.java | 186 -- .../auxiliary/report/ui/TestReportFrame.java | 824 -------- .../report/ui/TestReportMainFrame.java | 412 ---- .../auxiliary/report/ui/TestReportUI.java | 26 - .../pres/auxiliary/tool/data/Condition.java | 23 - .../pres/auxiliary/tool/data/FilterData.java | 71 - .../tool/data/GroupNotFoundException.java | 38 - .../java/pres/auxiliary/tool/data/Logic.java | 232 --- .../auxiliary/tool/data/NumberCondition.java | 11 - .../auxiliary/tool/data/RelationType.java | 15 - .../data/RootConditionNotFoundException.java | 43 - .../pres/auxiliary/tool/file/DisposeFile.java | 2 - .../tool/{controller => file}/ReadFile.java | 2 +- .../tool/randomstring/IdCardType.java | 5 - .../CarLicecenType.java | 2 +- .../auxiliary/tool/string/IdCardType.java | 5 + .../IllegalStringLengthException.java | 2 +- .../MobleNumberType.java | 2 +- .../{randomstring => string}/PhoneType.java | 2 +- .../PresetString.java | 2 +- .../RandomString.java | 2 +- .../{randomstring => string}/RandomWord.java | 2 +- .../{randomstring => string}/RegionType.java | 2 +- .../{randomstring => string}/StringMode.java | 2 +- .../tool/ui/control/AutoNumberJTextArea.java | 77 - .../ui/control/InputDoSearchComboBox.java | 357 ---- .../work/selenium/datadriven/Functions.java | 4 +- .../element/NoSuchWindownException.java | 28 - .../work/selenium/event/AssertEvent.java | 65 +- .../selenium/event/extend/DataTableEvent.java | 396 ++++ .../auxiliary/work/selenium/tool/Log_Old.java | 237 --- .../work/selenium/tool/RecordTool.java | 1322 ------------ .../tool/RecordToolConfigException.java | 38 - .../auxiliary/work/selenium/tool/RunLog.java | 32 - .../pres/auxiliary/tool/date/TimeTest.java | 4 +- .../tool/randomstring/PresetStringTest.java | 3 + .../tool/randomstring/RandomWordTest.java | 3 + .../datadriven/TestNGDataDriverTest.java | 4 +- src/test/java/test/javase/RandomPhone.java | 4 +- src/test/java/test/javase/SweepPlan.java | 2 +- src/test/java/test/javase/TestArrayList.java | 60 +- src/test/java/test/javase/TestCase2.java | 4 +- src/test/java/test/javase/TestPresetStr.java | 8 +- .../java/test/javase/TestRandomString.java | 2 +- 54 files changed, 520 insertions(+), 7546 deletions(-) delete mode 100644 src/main/java/pres/auxiliary/report/AbstractReport.java delete mode 100644 src/main/java/pres/auxiliary/report/AutoTestReport.java delete mode 100644 src/main/java/pres/auxiliary/report/BugFilePosition.java delete mode 100644 src/main/java/pres/auxiliary/report/IncompatibleFileLayoutException.java delete mode 100644 src/main/java/pres/auxiliary/report/IncorrectBugVersionException.java delete mode 100644 src/main/java/pres/auxiliary/report/IncorrectGrammarException.java delete mode 100644 src/main/java/pres/auxiliary/report/InvalidBugListFileSignException.java delete mode 100644 src/main/java/pres/auxiliary/report/ReportFactory.java delete mode 100644 src/main/java/pres/auxiliary/report/ReportInter.java delete mode 100644 src/main/java/pres/auxiliary/report/TestReport.java delete mode 100644 src/main/java/pres/auxiliary/report/ui/SandMailFrame.java delete mode 100644 src/main/java/pres/auxiliary/report/ui/TestReportFrame.java delete mode 100644 src/main/java/pres/auxiliary/report/ui/TestReportMainFrame.java delete mode 100644 src/main/java/pres/auxiliary/report/ui/TestReportUI.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/Condition.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/FilterData.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/GroupNotFoundException.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/Logic.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/NumberCondition.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/RelationType.java delete mode 100644 src/main/java/pres/auxiliary/tool/data/RootConditionNotFoundException.java rename src/main/java/pres/auxiliary/tool/{controller => file}/ReadFile.java (95%) delete mode 100644 src/main/java/pres/auxiliary/tool/randomstring/IdCardType.java rename src/main/java/pres/auxiliary/tool/{randomstring => string}/CarLicecenType.java (80%) create mode 100644 src/main/java/pres/auxiliary/tool/string/IdCardType.java rename src/main/java/pres/auxiliary/tool/{randomstring => string}/IllegalStringLengthException.java (88%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/MobleNumberType.java (93%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/PhoneType.java (74%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/PresetString.java (95%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/RandomString.java (97%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/RandomWord.java (95%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/RegionType.java (92%) rename src/main/java/pres/auxiliary/tool/{randomstring => string}/StringMode.java (97%) delete mode 100644 src/main/java/pres/auxiliary/tool/ui/control/AutoNumberJTextArea.java delete mode 100644 src/main/java/pres/auxiliary/tool/ui/control/InputDoSearchComboBox.java delete mode 100644 src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java create mode 100644 src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java delete mode 100644 src/main/java/pres/auxiliary/work/selenium/tool/Log_Old.java delete mode 100644 src/main/java/pres/auxiliary/work/selenium/tool/RecordTool.java delete mode 100644 src/main/java/pres/auxiliary/work/selenium/tool/RecordToolConfigException.java delete mode 100644 src/main/java/pres/auxiliary/work/selenium/tool/RunLog.java diff --git a/src/main/java/pres/auxiliary/report/AbstractReport.java b/src/main/java/pres/auxiliary/report/AbstractReport.java deleted file mode 100644 index b59a653..0000000 --- a/src/main/java/pres/auxiliary/report/AbstractReport.java +++ /dev/null @@ -1,1810 +0,0 @@ -package pres.auxiliary.report; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Font; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFClientAnchor; -import org.apache.poi.xssf.usermodel.XSSFDrawing; -import org.apache.poi.xssf.usermodel.XSSFFont; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFParagraph; -import org.apache.poi.xwpf.usermodel.XWPFRun; -import org.apache.poi.xwpf.usermodel.XWPFTable; -import org.apache.poi.xwpf.usermodel.XWPFTableCell; -import org.apache.poi.xwpf.usermodel.XWPFTableRow; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.NumberTickUnit; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.LineAndShapeRenderer; -import org.jfree.chart.title.TextTitle; -import org.jfree.data.category.DefaultCategoryDataset; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; - -import com.jacob.activeX.ActiveXComponent; -import com.jacob.com.ComThread; -import com.jacob.com.Dispatch; -import com.jacob.com.Variant; -import com.opencsv.CSVReader; - -/** - * 该类用于定义生成测试报告类共用的方法 - * - * @author 彭宇琦 - */ -// TODO 添加文件不存在时的限制 -public abstract class AbstractReport implements ReportInter { - /** - * 用于存储生成的测试报告存储的位置 - */ - private StringBuilder savePath = new StringBuilder("C:\\AutoTest\\Report\\"); - /** - * 用于存储测试报告的文件名 - */ - private StringBuilder fileName = new StringBuilder(""); - /** - * 用于判断是否允许打开文件夹,默认打开 - */ - private boolean isOpenFolder = true; - - /** - * 用于存储各版本Bug的信息 - */ - private File verBugNumber = new File( - "ConfigurationFiles/ReportConfigurationFile/PreviousVerisionBugNumber.xml"); - - /** - * 用于存储当前报告的项目名称 - */ - private String projectedName = ""; - - /** - * 用于存储从禅道上导出的BUG列表文件 - */ - protected File bugListFile; - - /** - * 用于存储Bug汇总表中的所有信息 - */ - private List bugList = null; - - /** - * 用于存储严重BUG的信息 - */ - private List bugInformations = new ArrayList<>(); - - private static Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}",Pattern.CASE_INSENSITIVE); - - /** - * 用于返回严重BUG的信息 - * @return 严重BUG的信息列表 - */ - public List getBugInformations() { - return bugInformations; - } - - /** - * 该方法返回测试报告的文件名称 - * - * @return 测试报告的文件名称 - */ - public String getFileName() { - return fileName.toString(); - } - - /** - * 该方法用于设置测试报告文件名称 - * - * @param fileName - * 测试报告的文件名称 - */ - public void setFileName(String fileName) { - // 判断传入的测试结果文件名称是否符合windows下的命名规则,若不符合,则抛出IncorrectDirectoryException异常 - if (!MakeDirectory.isFileName(fileName)) { - throw new IncorrectDirectoryException("不合理的文件名称,文件名称:" + fileName); - } - - // 通过判断后,则清空xmlName存储的信息并将新的文件名称放入xmlName种属性中 - this.fileName.delete(0, this.fileName.length()); - this.fileName.append(fileName); - } - - /** - * 该方法用于返回测试报告文件存放的位置 - * - * @return 测试报告文件存放的位置 - */ - public String getSavePath() { - return savePath.toString(); - } - - /** - * 该方法用于重新设置测试报告文件存放的路径,并将Document对象指向新的XML文件 - * - * @param savePath - * 测试报告的存放路径 - */ - public void setSavePath(String savePath) { - // 将传入的参数进行格式化 - StringBuilder sb = new StringBuilder(savePath); - sb = MakeDirectory.formatPath(sb); - - // 判断格式化后的文件路径格式是否符合windonws下文件路径的命名规则,不符合则抛出异常 - if (!MakeDirectory.isPath(sb.toString())) { - throw new IncorrectDirectoryException("不合理的文件夹路径,文件路径:" - + sb.toString()); - } - - // 将文件路径设置入属性中 - this.savePath = sb; - } - - /** - * 用于返回是否允许直接打开文件夹 - * - * @return - */ - public boolean isOpenFolder() { - return isOpenFolder; - } - - /** - * 用于设置是否直接打开文件夹 - * - * @param isOpenFolder - */ - public void setOpenFolder(boolean isOpenFolder) { - this.isOpenFolder = isOpenFolder; - } - - /** - * 该方法用于打印测试报告,需要结合jacob包,以及配置好jacob-1.17-xxx.dll文件 - * - * @param report - * 测试报告文件对象 - * @param printName - * 打印机的名称 - */ - public void printReport(File report, String printName) { - // 获取并存储待打印文件的绝对路径 - String path = report.getAbsolutePath(); - - // 初始化COM线程 - ComThread.InitSTA(); - // 使用Jacob创建 ActiveX部件对象: - ActiveXComponent word = new ActiveXComponent("Word.Application"); - - // 打开Word文档 - Dispatch doc = null; - // 这里Visible是控制文档打开后是可见还是不可见,若是静默打印,那么第三个参数就设为false - Dispatch.put(word, "Visible", new Variant(false)); - // 第二个参数中跟着的字符串中是打印机的名称 - word.setProperty("ActivePrinter", new Variant(printName)); - Dispatch docs = word.getProperty("Documents").toDispatch(); - doc = Dispatch.call(docs, "Open", path).toDispatch(); - - Dispatch.call(doc, "PrintOut");// 打印 - if (doc != null) { - Dispatch.call(doc, "Close", new Variant(0)); - } - // 释放资源 - ComThread.Release(); - } - - /** - * 该方法用于读取测试报告模板 - * - * @param xd - * 指向word文档的XWPFDocument对象 - * @param params - * 存储替换本的容器 - * @throws IOException - */ - protected void readeTemplet(XWPFDocument xd, Map params) - throws IOException { - // 用于获取所有word上所有的表格 - Iterator iterator = xd.getTablesIterator(); - // 用于获取单独的表格 - XWPFTable table; - // 用于存储获取到表格上所有的行 - List rows; - // 用于存储表格上所有的列 - List cells; - // 用于获取到列中的所有段落 - List paras; - - // 循环,获取文档中所有的表格 - while (iterator.hasNext()) { - // 获取文档中的表格 - table = iterator.next(); - // 获取表格中的所有行 - rows = table.getRows(); - - // 循环用于获取行中所有的行 - for (int i = 0; i < rows.size(); i++) { - cells = rows.get(i).getTableCells(); - - // 用于获取列中所有的列 - for (int j = 0; j < cells.size(); j++) { - paras = cells.get(j).getParagraphs(); - - // 判断获取的行数是否为第一行,若是第一行,则需要设计其样式 - if (i != 0) { - // 判断文本是否 - if (i == 9) { - // 分别查找段落中待替换的文本 - for (int k = 0; k < paras.size(); k++) { - replaceContent(paras.get(k), params); - } - } else { - // 分别查找段落中待替换的文本 - for (int k = 0; k < paras.size(); k++) { - replaceTempet(paras.get(k), params); - } - } - } else { - // 分别查找段落中待替换的文本 - for (int k = 0; k < paras.size(); k++) { - replaceTitleTempet(paras.get(k), params); - } - } - } - } - } - - // 定义文件,用于创建存储生成的模版的文件夹 - File f = new File(savePath.toString() + fileName.toString()); - if (!f.exists()) { - f.mkdirs(); - } - - FileOutputStream fop = new FileOutputStream(f - + ("\\" + fileName.toString() + ".docx")); - xd.write(fop); - fop.close(); - } - - /** - * 该方法用于替换模板中的其他文本 - * - * @param xp - * @param params - */ - private void replaceTempet(XWPFParagraph xp, Map params) { - // 用于匹配替换的字符 - Matcher matcher; - // 用于存储获取到的文字和替换后的文字 - String s = xp.getText(); - - // 通过正则进行匹配 - matcher = matcher(s); - - // 判断获取到的段落文字是否能匹配到正则 - if (matcher.find()) { - // 循环,对s中的文字进行修改 - while ((matcher = matcher(s)).find()) { - s = matcher.replaceFirst(String.valueOf(params.get(matcher - .group(1)))); - } - - // 获取到段落中所有的XWPFSRun对象,并通过循环将其全部删除 - List xrs = xp.getRuns(); - for (int i = 0; i < xrs.size(); i++) { - xp.removeRun(i); - i--; - } - - // 设置新的样式以及文字 - // xp.createRun().setText(s); - // 判断s中的内容是否包含换行符,如果包含,则需要对段落进行分段处理 - if (s.indexOf("\n") > -1) { - // 分割字符串 - String[] ss = s.split("\\n"); - for (int i = 0; i < ss.length; i++) { - XWPFRun run = xp.createRun();// 对某个段落设置格式 - run.setText(ss[i].trim()); - - // 判断当前的位置是否是最后一段,若是,则不加上换行 - if (i != ss.length - 1) { - run.addBreak();// 换行 - } - } - } else { - XWPFRun run = xp.createRun();// 对某个段落设置格式 - run.setText(s); - } - } - } - - /** - * 方法用于替换模板中的内容文本 - * - * @param xp - * @param params - */ - private void replaceContent(XWPFParagraph xp, Map params) { - // 用于匹配替换的字符 - Matcher matcher; - // 用于存储获取到的文字和替换后的文字 - String s = xp.getText(); - - // 通过正则进行匹配 - matcher = matcher(s); - - // 判断获取到的段落文字是否能匹配到正则 - if (matcher.find()) { - // 循环,对s中的文字进行修改 - while ((matcher = matcher(s)).find()) { - s = matcher.replaceFirst(String.valueOf(params.get(matcher - .group(1)))); - } - - // 获取到段落中所有的XWPFSRun对象,并通过循环将其全部删除 - List xrs = xp.getRuns(); - for (int i = 0; i < xrs.size(); i++) { - xp.removeRun(i); - i--; - } - - // 设置新的样式以及文字 - // xp.createRun().setText(s); - // 判断s中的内容是否包含换行符,如果包含,则需要对段落进行分段处理 - if (s.indexOf("\n") > -1) { - // 分割字符串 - String[] ss = s.split("\\n"); - for (int i = 0; i < ss.length; i++) { - XWPFRun run = xp.createRun();// 对某个段落设置格式 - run.addTab();// 段落前的Tab(等价于在段落前添加一个\t) - run.setText(ss[i].trim()); - - // 判断当前的位置是否是最后一段,若是,则不加上换行 - if (i != ss.length - 1) { - // 换行 - run.addBreak(); - } - } - } else { - XWPFRun run = xp.createRun();// 对某个段落设置格式 - run.addTab();// 段落前的Tab(等价于在段落前添加一个\t) - run.setText(s); - } - } - } - - /** - * 该方法用于替换模板中标题文本 - * - * @param xp - * @param params - */ - private void replaceTitleTempet(XWPFParagraph xp, Map params) { - // 用于匹配替换的字符 - Matcher matcher; - // 用于存储获取到的文字和替换后的文字 - String s = xp.getText(); - - // 通过正则进行匹配 - matcher = matcher(s); - - // 判断获取到的段落文字是否能匹配到正则 - if (matcher.find()) { - // 循环,对s中的文字进行修改 - while ((matcher = matcher(s)).find()) { - s = matcher.replaceFirst(String.valueOf(params.get(matcher - .group(1)))); - } - - // 获取到段落中所有的XWPFSRun对象,并通过循环将其全部删除 - List xrs = xp.getRuns(); - for (int i = 0; i < xrs.size(); i++) { - xp.removeRun(i); - i--; - } - - // 设置新的样式及文本 - XWPFRun xr = xp.createRun(); - // 设置字体大小(22磅为小二字体) - xr.setFontSize(22); - // 判断是否需要创建样式,若需要则创建,不需要则直接获取,之后重新设置 - CTRPr rpr = xr.getCTR().isSetRPr() ? xr.getCTR().getRPr() : xr - .getCTR().addNewRPr(); - CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr - .addNewRFonts(); - // 设置英文与数字的字体 - fonts.setAscii("Time New Roman"); - // 设置中文的字体 - fonts.setEastAsia("黑体"); - // 设置希腊文的字体 - fonts.setHAnsi("Time New Roman"); - // 设置文本 - xr.setText(s); - } - } - - /** - * 该方法用于匹配文本中的待替换的文本 - * - * @param str - * @return - */ - private Matcher matcher(String str) { - Matcher matcher = PATTERN.matcher(str); - return matcher; - } - - @Override - public String[] readFile(File bugListFile, int testDay) throws IOException { - // 用于存储测试结束时间,即当前的时间 - Date d = new Date(); - // 存储当前时间(测试结束时间) - String endTime = new SimpleDateFormat("yyyyMMdd").format(d); - - // 设置测试开始时间,调用Calendar类进行处理 - Calendar calendar = Calendar.getInstance(); - // 设置当前时间 - calendar.setTime(d); - // 设置当前的天数减去测试时间,得到测试开始时间 - calendar.add(Calendar.DAY_OF_MONTH, (1 - testDay)); - // 将得到的时间转换为Date进行返回 - d = calendar.getTime(); - String startTime = new SimpleDateFormat("yyyyMMdd").format(d); - - return readFile(bugListFile, startTime, endTime); - } - - /** - * 该方法用于读取Bug汇总表,其返回的数组存储的信息如下表所示:
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
s[0]:项目名称s[1]:当前版本s[2]:1级BUG数量s[3]:2级BUG数量
s[4]:3级BUG数量s[5]:4级BUG数量s[6]:激活1级BUG数量s[7]:激活2级BUG数量
s[8]:激活3级BUG数量s[9]:激活4级BUG数量s[10]:未解决的1级BUG数量s[11]:未解决的2级BUG数量
s[12]:延期解决1级BUG数量s[13]:延期解决2级BUG数量
- * - * @param bugListFile - * BUG汇总表 - * @param startTime - * 测试开始时间(字符串) - * @param endTime - * 测试结束时间(字符串) - * @return Bug汇总表中提取的信息 - * @throws IOException - */ - public String[] readFile(File bugListFile, String startTime, String endTime) - throws IOException { - // this.bugListFile = bugListFile; - - // TODO 新增字段时需要修改数组 - /* - * 数组字段说明 s[0]:项目名称 s[1]:当前版本 s[2]:1级BUG数量 s[3]:2级BUG数量 s[4]:3级BUG数量 - * s[5]:4级BUG数量 s[6]:激活1级BUG数量 s[7]:激活2级BUG数量 s[8]:激活3级BUG数量 - * s[9]:激活4级BUG数量 s[10]:未解决1级BUG数量 s[11]:未解决2级BUG数量 - */ - // 用于存储获取到的字符串组 - String[] temps = null; - - // 判断文件是否已经存在,不存在则读取Bug汇总表,并将其转换成List数组存入属性中 - if (this.bugListFile == null || !this.bugListFile.equals(bugListFile)) { - fileContentToList(bugListFile); - } - - temps = readVersionInformation(1); - - return readFile(bugListFile, temps[0].trim(), temps[1].trim(), startTime, endTime); - } - - public String[] readFile(File bugListFile, String projected, - String version, String startTime, String endTime) - throws IOException { - // TODO 新增字段时需要修改数组 - // 用于存储在Bug列表中读取到的信息 - String[] s = new String[14]; - - // 判断文件是否已经存在,不存在则读取Bug汇总表,并将其转换成List数组存入属性中 - if (this.bugListFile == null || !this.bugListFile.equals(bugListFile)) { - fileContentToList(bugListFile); - } - - // 存储项目名称 - projectedName = projected.trim(); - - // 存储项目及版本号 - s[0] = projected.trim(); - s[1] = version.trim(); - - // 用于计算一级Bug的数量 - int one = 0; - // 用于计算二级Bug的数量 - int two = 0; - // 用于计算三级Bug的数量 - int three = 0; - // 用于计算四级Bug的数量 - int four = 0; - - // 用于计算激活一级Bug的数量 - int activeOne = 0; - // 用于计算激活二级Bug的数量 - int activeTwo = 0; - // 用于计算激活三级Bug的数量 - int activeThree = 0; - // 用于计算激活四级Bug的数量 - int activeFour = 0; - - // 用于计算往期版本中延期的一级Bug的数量 - int delayOne = 0; - // 用于计算往期版本中延期的二级Bug的数量 - int delayTwo = 0; - //用于计算未解决的一级Bug的数量 - int noSulveOne = 0; - //用于计算未解决的二级Bug的数量 - int noSulveTwo = 0; - - // 读取BUG的总数 - int bugNumber = bugList.size(); - - // 循环,读取文件中所有Bug(读取时下标从1开始,表示从第二行开始读) - for (int i = 1; i < bugNumber; i++) { - // 判断读取的BUG是否为新提交的BUG - if (isNewBug(i, s[0], s[1], readDataInformation(i), startTime, endTime) == 1) { - // 判断读取到的Bug等级,其相应等级的数量加1 - switch (readBugLever(i)) { - case "1": - one++; - //添加严重BUG的信息至列表中 - bugInformations.add(new BugInformation(readBugID(i), readBugTitle(i), 1)); - break; - - case "2": - two++; - //添加严重BUG的信息至列表中 - bugInformations.add(new BugInformation(readBugID(i), readBugTitle(i), 2)); - break; - - case "3": - three++; - break; - - case "4": - four++; - break; - } - - // 继续循环,获取下一行的时间进行判断 - continue; - } - - // 若BUG不是新提交的BUG,则判断BUG是否为激活的BUG,依据则是判断版本号与激活次数是否大于1且版本为当前版本 - if (isActiveBug(i, s[0], s[1])) { - // 判断读取到的Bug等级,其相应等级的数量加1 - switch (readBugLever(i)) { - case "1": - activeOne++; - break; - - case "2": - activeTwo++; - break; - - case "3": - activeThree++; - break; - - case "4": - activeFour++; - break; - } - - continue; - } - - // 判断BUG是否为往期版本未解决的严重BUG - if (isOldBug(i) == 1) { - // 判断读取到的Bug等级,其相应等级的数量加1 - switch (readBugLever(i)) { - case "1": - noSulveOne++; - break; - - case "2": - noSulveTwo++; - break; - } - - continue; - } - - // 判断BUG是否为往期版本延期解决的严重BUG - if (isOldBug(i) == 2) { - // 判断读取到的Bug等级,其相应等级的数量加1 - switch (readBugLever(i)) { - case "1": - delayOne++; - break; - - case "2": - delayTwo++; - break; - } - - continue; - } - } - - // 存储不同等级的Bug数量 - s[2] = String.valueOf(one); - s[3] = String.valueOf(two); - s[4] = String.valueOf(three); - s[5] = String.valueOf(four); - s[6] = String.valueOf(activeOne); - s[7] = String.valueOf(activeTwo); - s[8] = String.valueOf(activeThree); - s[9] = String.valueOf(activeFour); - s[10] = String.valueOf(noSulveOne); - s[11] = String.valueOf(noSulveTwo); - s[12] = String.valueOf(delayOne); - s[13] = String.valueOf(delayTwo); - - // 添加当前版本BUG数量至XML文件中 - writeVersionBugNumber(s, (startTime + "-" + endTime)); - - // 用于创建测试报告的存储文件夹,已便于存储测试报告与处理后的Bug汇总表 - File f = new File(savePath.toString() + s[0] + "Ver" + s[1] + "版本测试报告"); - // 判断文件夹是否被创建,未被创建则创建文件夹 - if (!f.exists()) { - f.mkdirs(); - } - - // 将Bug汇总表写入到文件夹中 - FileOutputStream fop = new FileOutputStream(new File(f - + ("\\附:" + s[0] + "Ver" + s[1]) + "版本Bug汇总表.xlsx")); - createAccessory().write(fop); - fop.close(); - - return s; - } - - /** - * 该方法用于改进从禅道中导出的Bug汇总表 - * - * @throws IOException - */ - public XSSFWorkbook createAccessory() throws IOException { - // 用于创建excel文件对象 - XSSFWorkbook newxw = new XSSFWorkbook(); - // 创建新的Bug汇总表模版 - XSSFSheet newxs = createTemplet(newxw); - // 创建统计各个版本bug的sheet - XSSFSheet verBugXs = createVerBugTemplet(newxw); - // 读取存储bug数量的xml文件 - Document dom = null; - try { - dom = new SAXReader().read(verBugNumber); - } catch (DocumentException e) { - e.printStackTrace(); - } - - // 读取Bug汇总表,并将其转换成List数组存入属性中 - if (bugList == null) { - fileContentToList(bugListFile); - } - - // 获取BUG的总条数 - int rowNum = bugList.size(); - - // 读取原汇总表中的Bug标题中的取值,复制到新的汇总表中 - for (int i = 1; i < rowNum; i++) { - // 用于创建新汇总表中的行 - XSSFRow newxr = newxs.createRow(i); - XSSFCell newxc; - String s = null; - - // 复制Bug编号的内容 - s = bugList.get(i)[BugFilePosition.ID]; - // 在新的模版中创建第i行第1列 - newxc = newxr.createCell(0); - // 将s中的内容放入单元格中 - newxc.setCellValue(s); - // 设置单元格的样式 - newxc.setCellStyle(style3(newxw)); - - // 复制所属产品的内容 - s = bugList.get(i)[BugFilePosition.PRODUCT]; - newxc = newxr.createCell(1); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 通过标识符复制所属模块的内容 - s = bugList.get(i)[BugFilePosition.MODULE]; - newxc = newxr.createCell(2); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 通过标识符复制所属项目的内容 - s = bugList.get(i)[BugFilePosition.PROJECT]; - newxc = newxr.createCell(3); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制Bug标题的内容 - s = bugList.get(i)[BugFilePosition.TITLE]; - newxc = newxr.createCell(4); - newxc.setCellValue(s); - newxc.setCellStyle(style2(newxw)); - - // 复制严重程度的内容 - s = bugList.get(i)[BugFilePosition.SIGNIFICANCE]; - newxc = newxr.createCell(5); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制Bug类型的内容 - s = bugList.get(i)[BugFilePosition.TYPE]; - newxc = newxr.createCell(6); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制重现步骤的内容 - s = bugList.get(i)[BugFilePosition.STEP]; - newxc = newxr.createCell(7); - newxc.setCellValue(s); - newxc.setCellStyle(style2(newxw)); - - // 复制激活次数的内容 - s = bugList.get(i)[BugFilePosition.ACTIVE_COUNT]; - newxc = newxr.createCell(8); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制由谁创建的内容 - s = bugList.get(i)[BugFilePosition.CREATE_PERSON]; - newxc = newxr.createCell(9); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制创建时间的内容 - s = bugList.get(i)[BugFilePosition.CREATE_TIME]; - newxc = newxr.createCell(10); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制影响版本的内容 - s = bugList.get(i)[BugFilePosition.VERSION]; - newxc = newxr.createCell(11); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - - // 复制指派给的内容 - s = bugList.get(i)[BugFilePosition.ASSIGN_PERSON]; - newxc = newxr.createCell(12); - newxc.setCellValue(s); - newxc.setCellStyle(style3(newxw)); - } - - // 添加各版本的BUG统计 - Element e = (Element) (dom.selectSingleNode("bug/projected[@name='" - + projectedName + "']")); - // 读取所有的version标签 - @SuppressWarnings("unchecked") - List verEs = e.elements(); - // 循环,将Bug记录信息写入文件中 - for (int i = 0; i < verEs.size(); i++) { - // 用于创建新汇总表中的行 - XSSFRow verBugXr = verBugXs.createRow(i + 1); - XSSFCell verBugXc; - - // 存储版本信息 - verBugXc = verBugXr.createCell(0); - verBugXc.setCellValue(verEs.get(i).attributeValue("version")); - verBugXc.setCellStyle(style3(newxw)); - - // 存储该版本一级Bug的数量 - verBugXc = verBugXr.createCell(1); - verBugXc.setCellValue(verEs.get(i).element("one") - .attributeValue("number")); - verBugXc.setCellStyle(style3(newxw)); - - // 存储该版本二级Bug的数量 - verBugXc = verBugXr.createCell(2); - verBugXc.setCellValue(verEs.get(i).element("two") - .attributeValue("number")); - verBugXc.setCellStyle(style3(newxw)); - - // 存储该版本三级Bug的数量 - verBugXc = verBugXr.createCell(3); - verBugXc.setCellValue(verEs.get(i).element("three") - .attributeValue("number")); - verBugXc.setCellStyle(style3(newxw)); - - // 存储该版本四级Bug的数量 - verBugXc = verBugXr.createCell(4); - verBugXc.setCellValue(verEs.get(i).element("four") - .attributeValue("number")); - verBugXc.setCellStyle(style3(newxw)); - } - - // 画图的顶级管理器,一个sheet只能获取一个(一定要注意这点) - XSSFDrawing patriarch = verBugXs.createDrawingPatriarch(); - // 八个参数,前四个表示图片离起始单元格和结束单元格边缘的位置, - // 后四个表示起始和结束单元格的位置,如下表示从第7列到第13列,从第1行到第16行,需要注意excel起始位置是0 - XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 6, - (short) 1, (short) 14, (short) 16); - // anchor.setAnchorType(3); - // 插入图片 - patriarch.createPicture(anchor, newxw.addPicture(plotBugCurve(verBugXs) - .toByteArray(), Workbook.PICTURE_TYPE_PNG)); - - // 返回新的模版对象 - return newxw; - } - - /** - * 用于创建Bug数量曲线的方法,其需要传入一个工作表对象,其工作表中,数据的格式如下:
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
版本一级Bug数量二级Bug数量三级Bug数量四级Bug数量
V0.10253
···············
- * - * @param xs - * 工作表sheet对象(poi) - * @return - */ - public ByteArrayOutputStream plotBugCurve(XSSFSheet xs) { - // 用于输出图片的字节流 - ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); - - // 用于存储从sheet中读取到的数据,之后将用其作图 - // 存储版本信息 - List versionList = new ArrayList(); - // 存储Bug信息 - List oneList = new ArrayList(); - List twoList = new ArrayList(); - List threeList = new ArrayList(); - List fourList = new ArrayList(); - - // 读取sheet中的数据 - for (int i = 1; i < xs.getLastRowNum() + 1; i++) { - // 读取版本信息 - versionList.add("V" + xs.getRow(i).getCell(0).getStringCellValue()); - // 读取Bug数量(按照getNumericCellValue方法获取的数据为double,需要强转为int) - oneList.add(Integer.valueOf(xs.getRow(i).getCell(1) - .getStringCellValue())); - twoList.add(Integer.valueOf(xs.getRow(i).getCell(2) - .getStringCellValue())); - threeList.add(Integer.valueOf(xs.getRow(i).getCell(3) - .getStringCellValue())); - fourList.add(Integer.valueOf(xs.getRow(i).getCell(4) - .getStringCellValue())); - } - - // 反序数组,以便于作图 - /* - * Collections.reverse(versionList); Collections.reverse(oneList); - * Collections.reverse(twoList); Collections.reverse(threeList); - * Collections.reverse(fourList); - */ - - // 添加数据入图表 - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - for (int i = 0; i < versionList.size(); i++) { - String version = versionList.get(i); - dataset.addValue(oneList.get(i), "一级Bug数量", version); - dataset.addValue(twoList.get(i), "二级Bug数量", version); - dataset.addValue(threeList.get(i), "三级Bug数量", version); - dataset.addValue(fourList.get(i), "四级Bug数量", version); - } - JFreeChart chart = ChartFactory.createLineChart("Bug数量曲线", "版本", "数量", - dataset, PlotOrientation.VERTICAL, true, true, true); - - // 设置图例字体 - chart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 10)); - - // 设置标题字体 - chart.setTitle(new TextTitle(chart.getTitle().getText(), new Font("黑体", - Font.BOLD, 12))); - - // 图形的绘制结构对象 - CategoryPlot plot = chart.getCategoryPlot(); - - // 获取显示线条的对象 - LineAndShapeRenderer lasp = (LineAndShapeRenderer) plot.getRenderer(); - - // 设置拐点是否可见/是否显示拐点 - lasp.setBaseShapesVisible(true); - - // 设置拐点不同用不同的形状 - lasp.setDrawOutlines(true); - - // 设置线条是否被显示填充颜色 - lasp.setUseFillPaint(false); - - // 设置折点的大小 - lasp.setSeriesOutlineStroke(0, new BasicStroke(0.025F)); - lasp.setSeriesOutlineStroke(1, new BasicStroke(0.05F)); - - // 设置网格线 - plot.setDomainGridlinePaint(Color.gray); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinePaint(Color.gray); - plot.setRangeGridlinesVisible(true); - - // x轴 - CategoryAxis domainAxis = plot.getDomainAxis(); - // 设置x轴不显示,即让x轴和数据区重合 - domainAxis.setAxisLineVisible(false); - // x轴标题 - domainAxis.setLabelFont(new Font("黑体", Font.BOLD, 10)); - // x轴数据倾斜 - domainAxis.setCategoryLabelPositions(CategoryLabelPositions - .createUpRotationLabelPositions(0.95D)); - // X轴坐标上数值字体 - domainAxis.setTickLabelFont(new Font("黑体", Font.BOLD, 10)); - - // 设置Y轴间隔 - NumberAxis numAxis = (NumberAxis) plot.getRangeAxis(); - numAxis.setTickUnit(new NumberTickUnit(50)); - // y轴 - ValueAxis rangeAxis = plot.getRangeAxis(); - rangeAxis.setLabelFont(new Font("黑体", Font.BOLD, 10)); - - // 设置y轴不显示,即和数据区重合 - rangeAxis.setAxisLineVisible(false); - - // y轴坐标上数值字体 - rangeAxis.setTickLabelFont(new Font("黑体", Font.BOLD, 10)); - rangeAxis.setFixedDimension(0); - CategoryPlot cp = chart.getCategoryPlot(); - - // 背景色设置 - cp.setBackgroundPaint(Color.WHITE); - cp.setRangeGridlinePaint(Color.GRAY); - - try { - ChartUtilities.writeChartAsPNG(byteArrayOut, chart, 400, 200); - } catch (IOException e) { - e.printStackTrace(); - } - - return byteArrayOut; - } - - /** - * 该方法用于创建一个Bug汇总表的附件模版 - * - * @return Excel表对象 - */ - private XSSFSheet createTemplet(XSSFWorkbook xw) { - // 创建工作簿 - XSSFSheet xs = xw.createSheet("Bug"); - // 创建表格的第一行,并设置高度 - XSSFRow xr = xs.createRow(0); - xs.getRow(0).setHeight((short) (26.00 * 20)); - - // 创建Bug编号项目及其样式 - // 创建第一列 - XSSFCell xc = xr.createCell(0); - // 创建该列的值 - xc.setCellValue("Bug编号"); - // 创建该列的样式 - xc.setCellStyle(style1(xw)); - // 创建该列的宽度 - xs.setColumnWidth(0, (short) (5.7 * 256)); - - // 创建所属产品及其样式 - xc = xr.createCell(1); - xc.setCellValue("所属产品"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(1, (short) (9.5 * 256)); - - // 创建所属模块及其样式 - xc = xr.createCell(2); - xc.setCellValue("所属模块"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(2, (short) (9.5 * 256)); - - // 创建所属项目及其样式 - xc = xr.createCell(3); - xc.setCellValue("所属项目"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(3, (short) (9.5 * 256)); - - // 创建Bug标题及其样式 - xc = xr.createCell(4); - xc.setCellValue("Bug标题"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(4, (short) (33.13 * 256)); - - // 创建严重程度及其样式 - xc = xr.createCell(5); - xc.setCellValue("严重程度"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(5, (short) (5.7 * 256)); - - // 创建Bug类型及其样式 - xc = xr.createCell(6); - xc.setCellValue("Bug类型"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(6, (short) (9.5 * 256)); - - // 创建重现步骤及其样式 - xc = xr.createCell(7); - xc.setCellValue("重现步骤"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(7, (short) (39.00 * 256)); - - // 创建激活次数及其样式 - xc = xr.createCell(8); - xc.setCellValue("激活次数"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(8, (short) (5.7 * 256)); - - // 创建由谁创建及其样式 - xc = xr.createCell(9); - xc.setCellValue("由谁创建"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(9, (short) (7.50 * 256)); - - // 创建创建日期及其样式 - xc = xr.createCell(10); - xc.setCellValue("创建日期"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(10, (short) (11.00 * 256)); - - // 创建影响版本及其样式 - xc = xr.createCell(11); - xc.setCellValue("影响版本"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(11, (short) (12.38 * 256)); - - // 创建指派给及其样式 - xc = xr.createCell(12); - xc.setCellValue("指派给"); - xc.setCellStyle(style1(xw)); - xs.setColumnWidth(12, (short) (7.50 * 256)); - - // 添加筛选按钮,筛选按钮的添加是按表格上的标识添加的,所以需要对列数进行转换 - // 例如,要添加前三列的搜索,则写为:xs.setAutoFilter(CellRangeAddress.valueOf("A1:C1")); - xs.setAutoFilter(CellRangeAddress.valueOf((String.valueOf((char) (65)) - + "1:" + String.valueOf((char) (65 + 13 - 1)) + "1"))); - - // 冻结单元格 - xs.createFreezePane(0, 1, 1, 1); - - return xs; - } - - /** - * 用于创建各个版本Bug统计 - * - * @param xw - * @return - */ - private XSSFSheet createVerBugTemplet(XSSFWorkbook xw) { - // 创建工作簿 - XSSFSheet xs = xw.createSheet("各个版本Bug数量统计"); - // 创建表格的第一行 - XSSFRow xr = xs.createRow(0); - - // 创建Bug编号项目及其样式 - XSSFCell xc = xr.createCell(0); - xc.setCellValue("版本"); - xc.setCellStyle(style3(xw)); - xs.setColumnWidth(0, (short) (12.00 * 256)); - - xc = xr.createCell(1); - xc.setCellValue("一级Bug数量"); - xc.setCellStyle(style3(xw)); - xs.setColumnWidth(1, (short) (12.00 * 256)); - - xc = xr.createCell(2); - xc.setCellValue("二级Bug数量"); - xc.setCellStyle(style3(xw)); - xs.setColumnWidth(2, (short) (12.00 * 256)); - - xc = xr.createCell(3); - xc.setCellValue("三级Bug数量"); - xc.setCellStyle(style3(xw)); - xs.setColumnWidth(3, (short) (12.00 * 256)); - - xc = xr.createCell(4); - xc.setCellValue("四级Bug数量"); - xc.setCellStyle(style3(xw)); - xs.setColumnWidth(4, (short) (12.00 * 256)); - - // 添加筛选按钮,筛选按钮的添加是按表格上的标识添加的,所以需要对列数进行转换 - // 例如,要添加前三列的搜索,则写为:xs.setAutoFilter(CellRangeAddress.valueOf("A1:C1")); - xs.setAutoFilter(CellRangeAddress.valueOf("A1:A1")); - - return xs; - } - - /** - * 该方法用于设置水平居中、垂直居中、字体加粗的样式 - */ - private XSSFCellStyle style1(XSSFWorkbook xw) { - XSSFCellStyle xcs = xw.createCellStyle(); - // 设置内容的水平居中对齐 - xcs.setAlignment(HorizontalAlignment.CENTER); - // 设置内容的垂直居中对齐 - xcs.setVerticalAlignment(VerticalAlignment.CENTER); - // 设置单元格自动换行 - xcs.setWrapText(true); - // 设置字体的样式 - xcs.setFont(font1(xw)); - return xcs; - } - - /** - * 该方法用于设置水平左对齐、垂直居中的样式 - */ - private XSSFCellStyle style2(XSSFWorkbook xw) { - XSSFCellStyle xcs = xw.createCellStyle(); - // 设置内容的水平居中对齐 - xcs.setAlignment(HorizontalAlignment.LEFT); - // 设置内容的垂直居中对齐 - xcs.setVerticalAlignment(VerticalAlignment.CENTER); - // 设置单元格自动换行 - xcs.setWrapText(true); - // 设置字体的样式 - xcs.setFont(font2(xw)); - return xcs; - } - - /** - * 该方法用于设置水平居中、垂直居中的样式 - */ - private XSSFCellStyle style3(XSSFWorkbook xw) { - XSSFCellStyle xcs = xw.createCellStyle(); - // 设置内容的水平居中对齐 - xcs.setAlignment(HorizontalAlignment.CENTER); - // 设置内容的垂直居中对齐 - xcs.setVerticalAlignment(VerticalAlignment.CENTER); - // 设置单元格自动换行 - xcs.setWrapText(true); - // 设置字体的样式 - xcs.setFont(font2(xw)); - return xcs; - } - - /** - * 该方法用于设置加粗的字体 - */ - private XSSFFont font1(XSSFWorkbook xw) { - XSSFFont xf = xw.createFont(); - // 设置字体名称 - xf.setFontName("宋体"); - // 设置字体大小,注意,字体大小单位为磅,小四字体对应12磅 - xf.setFontHeightInPoints((short) 12); - // 设置字体加粗 - xf.setBold(true); - return xf; - } - - /** - * 该方法用于设置普通的字体 - */ - private XSSFFont font2(XSSFWorkbook xw) { - XSSFFont xf = xw.createFont(); - // 设置字体名称 - xf.setFontName("宋体"); - // 设置字体大小,注意,字体大小单位为磅,小四字体对应12磅 - xf.setFontHeightInPoints((short) 12); - return xf; - } - - /** - * 该方法用于读取并通过字符串的形式返回单元格的值 - * - * @param cell - * @return - */ - // - // private String valueOf(XSSFCell cell) { - // String s; - // - // if (cell.getCellTypeEnum().equals(CellType.STRING)) { - // s = cell.getStringCellValue(); - // } - // - // else if (cell.getCellTypeEnum().equals(CellType.NUMERIC)) { - // if (HSSFDateUtil.isCellDateFormatted(cell)) { - // double d = cell.getNumericCellValue(); - // Date date = HSSFDateUtil.getJavaDate(d); - // s = new SimpleDateFormat("yyyy-MM-dd").format(date); - // } else { - // s = String.valueOf((int) cell.getNumericCellValue()); - // } - // } else if (cell.getCellTypeEnum().equals(CellType.BLANK)) { - // s = ""; - // } else if (cell.getCellTypeEnum().equals(CellType.BOOLEAN)) { - // s = String.valueOf(cell.getBooleanCellValue()); - // } else if (cell.getCellTypeEnum().equals(CellType.ERROR)) { - // s = ""; - // } else if (cell.getCellTypeEnum().equals(CellType.FORMULA)) { - // s = cell.getCellFormula().toString(); - // } else { - // s = null; - // } - // - // return s; - // } - - /** - * 用于识别文件的格式并将其转换成数组形式存储在类属性bugList中 - * - * @param bugListFile - * @throws IOException - */ - private void fileContentToList(File bugListFile) throws IOException { - this.bugListFile = bugListFile; - - // TODO 添加标识符,用以判断传入的文件是csv文件还是xlsx文件 - if (this.bugListFile.getName().indexOf(".xlsx") > -1) { - bugList = new ArrayList<>(); - - // 读取导出的bug列表文件 - FileInputStream fip = new FileInputStream(this.bugListFile); - // 通过XSSFWorkbook对表格文件进行操作 - XSSFWorkbook xw = new XSSFWorkbook(fip); - // 关闭流 - fip.close(); - - // 读取工作簿(禅道导出的数据在未改动的情况下工作簿的名称为Bug) - XSSFSheet xs = xw.getSheetAt(0); - - // 循环,将整个表格转换成List的形式 - // 读取所有行 - int cellNum = 0;// 用于存储列的总数 - for (int i = 0; i < xs.getLastRowNum() + 1; i++) { - XSSFRow xr = xs.getRow(i); - // 判断是否是第一行数据,由于每行最后一列直接获取可能导致获取到的数据不统一,但第一行的所有列是最全的(标题列),所以按照第一行进行获取所有列 - if (i == 0) { - cellNum = xr.getLastCellNum(); - } - // 定义存储列数据的数组 - String[] s = new String[cellNum]; - - // 读取每行的所有列 - for (int j = 0; j < cellNum; j++) { - // 存储单元格中的内容 - // 当读取到日期时,需要更正日期格式 - if (j == 20) { - // 由于专业版与开源版读取到的数据类型有些偏差,故需要通过读取数据时是否报错来判断禅道的版本,当抛出IllegalStateException异常时,则禅道使用的是开源版 - try { - // 专业版的读法 - s[j] = xs.getRow(i).getCell(j).getStringCellValue(); - } catch (IllegalStateException e) { - // 开源版的读法 - s[j] = new SimpleDateFormat("yyyyMMdd") - .format(DateUtil.getJavaDate(xs.getRow(i) - .getCell(j).getNumericCellValue()));// - } - } else { - // 若不是日期,则按照正常的方式读取,若读到空单元格时会出现空指针异常,此时需要将该行进行处理,将其存储为空 - try { - s[j] = xr.getCell(j).toString(); - } catch (NullPointerException e) { - s[j] = ""; - } - } - } - // 存储一行单元格中的内容 - bugList.add(s); - } - - xw.close(); - } else if (this.bugListFile.getName().indexOf(".csv") > -1) { - CSVReader csvReader = new CSVReader( - new FileReader(this.bugListFile)); - bugList = csvReader.readAll(); - csvReader.close(); - - } else if (this.bugListFile.getName().indexOf(".xls") > -1) { - bugList = new ArrayList<>(); - - // 读取导出的bug列表文件 - FileInputStream fip = new FileInputStream(this.bugListFile); - // 通过XSSFWorkbook对表格文件进行操作 - HSSFWorkbook hw = new HSSFWorkbook(fip); - // 关闭流 - fip.close(); - - // 读取工作簿(禅道导出的数据在未改动的情况下工作簿的名称为Bug) - HSSFSheet hs = hw.getSheetAt(0); - - // 循环,将整个表格转换成List的形式 - // 读取所有行 - int cellNum = 0;// 用于存储列的总数 - for (int i = 0; i < hs.getLastRowNum() + 1; i++) { - HSSFRow hr = hs.getRow(i); - // 判断是否是第一行数据,由于每行最后一列直接获取可能导致获取到的数据不统一,但第一行的所有列是最全的(标题列),所以按照第一行进行获取所有列 - if (i == 0) { - cellNum = hr.getLastCellNum(); - } - // 定义存储列数据的数组 - String[] s = new String[cellNum]; - - // 读取每行的所有列 - for (int j = 0; j < cellNum; j++) { - // 存储单元格中的内容 - // 当读取到日期时,需要更正日期格式 - if (j == 20) { - // 由于专业版与开源版读取到的数据类型有些偏差,故需要通过读取数据时是否报错来判断禅道的版本,当抛出IllegalStateException异常时,则禅道使用的是开源版 - try { - // 专业版的读法 - s[j] = hs.getRow(i).getCell(j).getStringCellValue(); - } catch (IllegalStateException e) { - // 开源版的读法 - s[j] = new SimpleDateFormat("yyyyMMdd") - .format(DateUtil.getJavaDate(hs.getRow(i) - .getCell(j).getNumericCellValue()));// - } - } else { - // 若不是日期,则按照正常的方式读取,若读到空单元格时会出现空指针异常,此时需要将该行进行处理,将其存储为空 - try { - s[j] = hr.getCell(j).toString(); - } catch (NullPointerException e) { - s[j] = ""; - } - } - } - // 存储一行单元格中的内容 - bugList.add(s); - } - - hw.close(); - } else { - throw new IncompatibleFileLayoutException("不兼容的文件格式:" - + bugListFile.getName()); - } - } - - /** - * 用于向PreviousVerisionBugNumber.xml中添加当前版本的BUG数量 - * - * @param s - * 从BUG汇总表中记录的数据 - * @param startTime - * @param endTime - * @throws UnsupportedEncodingException - * @throws IOException - */ - public void writeVersionBugNumber(String[] s, String time) - throws UnsupportedEncodingException, IOException { - // 设置统计当前版本BUG至XML文件上 - Document dom = null; - - String judge_BUG = "bug"; - String judge_PROJECTED = "projected"; - - try { - dom = new SAXReader().read(verBugNumber); - } catch (DocumentException e1) { - e1.printStackTrace(); - } - // 获取根节点 - Element element = dom.getRootElement(); - - // 读取所有的项目标签,判断当前项目是否已存入XML中,若已存在,则获取其标签,若不存在,则创建项目标签 - @SuppressWarnings("unchecked") - List es = element.elements("projected"); - for (Element e : es) { - // 判断当前元素的name属性是否为当前的项目名称,是则直接获取当前元素,并结束循环 - if (e.attributeValue("name").equals(s[0])) { - element = e; - break; - } - } - - // 判断变量element的标签名称是否仍为根节点名称,若是,则说明当前项目未创建过标签,则直接创建项目标签及版本标签 - if (judge_BUG.equals(element.getName())) { - element = element.addElement("projected"); - element.addAttribute("name", s[0]); - - // 创建版本,并将element指向版本标签 - element = element.addElement("version"); - element.addAttribute("version", s[1]); - element.addAttribute("time", time); - - // 创建记录BUG数量的标签 - element.addElement("one").addAttribute("number", ""); - element.addElement("two").addAttribute("number", ""); - element.addElement("three").addAttribute("number", ""); - element.addElement("four").addAttribute("number", ""); - } else { - // 如果查找到项目元素,则再查找当前版本是否存在,方法同查找项目标签 - @SuppressWarnings("unchecked") - List vs = element.elements("version"); - for (Element v : vs) { - if (v.attributeValue("version").equals(s[1])) { - element = v; - break; - } - } - - // 判断element的标签名称是否仍为projected,若是,则说明循环后未获取到相应的版本,则创建 - if (judge_PROJECTED.equals(element.getName())) { - // 创建版本,并将element指向版本标签 - element = element.addElement("version"); - element.addAttribute("version", s[1]); - element.addAttribute("time", time); - - // 创建记录BUG数量的标签 - element.addElement("one").addAttribute("number", ""); - element.addElement("two").addAttribute("number", ""); - element.addElement("three").addAttribute("number", ""); - element.addElement("four").addAttribute("number", ""); - } else { - // 如果标签存在,则修改标签的时间信息 - element.attribute("time").setValue(time); - } - - } - - // 获取当前项目对应版本的标签(xpath方式搜索) - element = (Element) (dom.selectSingleNode("/bug/projected[@name=\"" - + s[0] + "\"]/version[@version=\"" + s[1] + "\"]")); - - // 将其值添加入xml文件中 - element.element("one").attribute("number").setValue(s[2]); - element.element("two").attribute("number").setValue(s[3]); - element.element("three").attribute("number").setValue(s[4]); - element.element("four").attribute("number").setValue(s[5]); - - // 使用dom4j的漂亮格式 - OutputFormat format = OutputFormat.createPrettyPrint(); - // 设置xml文件的编码方式 - format.setEncoding("GBK"); - // 写入xml - XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(verBugNumber), - format); - - xmlWriter.write(dom); - xmlWriter.close(); - - // 用于创建测试报告的存储文件夹,已便于存储测试报告与处理后的Bug汇总表 - File f = new File(savePath.toString() + s[0] + "Ver" + s[1] + "版本测试报告"); - // 判断文件夹是否被创建,未被创建则创建文件夹 - if (!f.exists()) { - f.mkdirs(); - } - - // 将Bug汇总表写入到文件夹中 - FileOutputStream fop = new FileOutputStream(new File(f - + ("\\附:" + s[0] + "Ver" + s[1]) + "版本Bug汇总表.xlsx")); - createAccessory().write(fop); - fop.close(); - } - - /** - * 用于获取Bug的版本信息,注意,需要根据标识符sign来传入文件类型,若sign为xlsx,则传入xs,bugList传入null;若为csv, - * 则xs传入null。 - * - * @param sign - * @param xs - * @param bugList - * @return - * @throws IOException - * @throws UnsupportedEncodingException - */ - private String[] readVersionInformation(int i) - throws UnsupportedEncodingException, IOException { - StringBuilder temp = new StringBuilder(); - String[] temps; - String[] s = new String[2]; - - // 定位到模版中的影响版本中(导出的数据中第22列,即V那一列为影响版本,那里可以读取到测试的项目名称及版本号) - temp.append(this.bugList.get(i)[BugFilePosition.VERSION]); - - // 判断版本号的分隔是否为Ver,之后按照版本号特定的字符进行分割,并存储获取到的数据到s中 - if (temp.indexOf("Ver") > -1) { - temps = temp.toString().split("Ver"); - } else if(temp.indexOf("V") > -1) { - temps = temp.toString().split("V"); - } else { - throw new IncorrectBugVersionException("列表第" + i + "条数据版本号不正确"); - } - - // 存储测试项目名称 - s[0] = temps[0].trim(); - - // 存储版本号,由于获取到的元素中还包含一个禅道的标识符,其格式为“(#xx)”,此时可以查找“(#”来将字符串进行删除 - s[1] = new StringBuilder(temps[1]).delete(temps[1].indexOf("(#"), - temps[1].length()).toString().trim(); - - return s; - } - - /** - * 读取时间信息 - * - * @param i - * @return - */ - private String readDataInformation(int i) { - StringBuilder temp = new StringBuilder(""); - // 判断新增BUG数的方法,先判断创建日期是否为当天,再判断其影响版本是否为当前版本,最后再判断其激活次数是否大于0 - // 通过标识符读取日期信息 - // 先保留该行注释,以便于以后开发专业版时有参考 - // if (sign.equals("xlsx")) { - // // 由于第一个提交的Bug时间会大于或等于测试开始时间,此时程序会读到表格的最后一行,若继续向下读 - // // 会造成获取不到值的情况,此时会抛出空指针异常,此处接收抛出的异常,之后结束整个循环 - // // 2018-6-23 备注: 我忘记当时的情况了,不敢改动这一段的代码··· - // try { - // // 定位到模版中的创建时间中(导出的数据中第21列,即U那一列为创建时间) - // // - // 由于专业版与开源版读取到的数据类型有些偏差,故需要通过读取数据时是否报错来判断禅道的版本,当抛出IllegalStateException异常时,则禅道使用的是开源版 - // try { - // temp.append(xs.getRow(i).getCell(20).getStringCellValue());// 专业版的读法 - // } catch (IllegalStateException e) { - // temp.append(new SimpleDateFormat("yyyyMMdd") - // .format(DateUtil.getJavaDate(xs.getRow(i).getCell(20).getNumericCellValue())));// - // 开源版的读法 - // } - // } catch (NullPointerException e) { - // } - // } else if (sign.equals("csv")) { - // // 读取bugList的i行20列 - // temp.append(bugList.get(i)[20]); - // } - - // 读取日期信息 - temp.append(bugList.get(i)[BugFilePosition.CREATE_TIME]); - int j; - // 删除获取到的文字中存在的分隔符 - while ((j = temp.indexOf("/")) > -1 || (j = temp.indexOf("-")) > -1) { - temp.delete(j, j + 1); - } - - return temp.toString(); - } - - /** - * 用于获取BUG的等级 - */ - private String readBugLever(int i) { - /* - * // 通过标识符判断BUG等级 // 读取严重程度的取值,并将相应的Bug等级的数量+1(严重程度在第9行,即I行) String - * bugLv = null; if (sign.equals("xlsx")) { // - * 获取Bug的等级,由于专业版与开源版读取到的数据类型有些偏差,故需要通过读取数据时是否报错来判断禅道的版本, - * 当抛出IllegalStateException异常时,则禅道使用的是开源版 try { bugLv = - * xs.getRow(i).getCell(8).getStringCellValue();// 专业版的读法 } catch - * (IllegalStateException e) { bugLv = String.valueOf((int) - * xs.getRow(i).getCell(8).getNumericCellValue());// 开源版的读法 } } else if - * (sign.equals("csv")) { bugLv = bugList.get(i)[8]; } - */ - - // 读取Bug等级 - String bugLv = bugList.get(i)[BugFilePosition.SIGNIFICANCE]; - if (bugLv.indexOf(".") > -1) { - bugLv = bugLv.substring(0, bugLv.indexOf(".")); - } - return bugLv; - } - - private String readBugTitle(int i) { - return bugList.get(i)[BugFilePosition.TITLE]; - } - - private String readBugID(int i) { - return bugList.get(i)[BugFilePosition.ID]; - } - - /** - * 用于判断查询的BUG是否为新发现的BUG
- * 三个状态:
- * 1表示当前Bug的创建时间在给定的时间以内
- * 0表示当前Bug的创建时间大于给定的时间
- * -1表示当前Bug的创建时间小于给定的时间 - */ - private int isNewBug(int i, String projected, String version, String temp, - String startTime, String endTime) { - // boolean is = false; - // 三个状态: - // 1表示当前Bug的创建时间在给定的时间以内 - // 0表示当前Bug的创建时间大于给定的时间 - // -1表示当前Bug的创建时间小于给定的时间 - int is = 0; - - // 读取当前BUG的影响版本 - String[] str1 = null; - try { - str1 = readVersionInformation(i); - } catch (IOException e) { - e.printStackTrace(); - } - - // 读取激活次数 - int count = (int) (Double - .valueOf(bugList.get(i)[BugFilePosition.ACTIVE_COUNT]) - .doubleValue()); - - // 将日期转换为数字进行比较,若得到的获取到的时间介于开始时间与结束时间之间时,则获取该Bug的等级 - // 读取日期信息 - if (Integer.valueOf(temp) >= Integer.valueOf(startTime) - && Integer.valueOf(temp) <= Integer.valueOf(endTime)) { - // 判断BUG的影响版本是否为当前版本(即判断影响版本是否与第一个版本一致) - if (str1[0].equals(projected) && str1[1].equals(version)) { - // 判断激活次数是否为0 - if (count == 0) { - // 若激活次数为0且BUG的创建时间在测试时间范围内,则返回1 - is = 1; - } - } - } else if (Integer.valueOf(temp) > Integer.valueOf(endTime)) { - // 若BUG的创建时间在测试时间大于测试结束时间,则返回0 - is = 0; - } else { - is = -1; - } - - return is; - } - - /** - * 判断是否为激活的BUG - */ - private boolean isActiveBug(int i, String projected, String version) { - boolean is = false; - // 读取严重程度的取值,并将相应的Bug等级的数量+1(严重程度在第9行,即I行) - // 获取Bug的等级,由于专业版与开源版读取到的数据类型有些偏差,故需要通过读取数据时是否报错来判断禅道的版本,当抛出IllegalStateException异常时,则禅道使用的是开源版 - // 若BUG不是新提交的BUG,则判断BUG是否为激活的BUG,依据则是判断版本号与激活次数是否大于1且版本为当前版本 - int count = (int) (Double - .valueOf(bugList.get(i)[BugFilePosition.ACTIVE_COUNT]) - .doubleValue()); - // 判断激活次数是否大于0 - if (count > 0) { - // 符对比影响版本 - String[] str1 = null; - try { - str1 = readVersionInformation(i); - } catch (IOException e) { - e.printStackTrace(); - } - // 判断BUG的影响版本是否为当前版本(即判断影响版本是否与第一个版本一致) - if (str1[0].equals(projected) && str1[1].equals(version)) { - is = true; - } - } - - return is; - } - - /** - * 统计往期的版本BUG,返回值有三个状态: - * 0表示往期非严重的BUG - * 1表示往期未解决的严重BUG - * 2表示往期延期解决的严重BUG - */ - private int isOldBug(int i) { - // 如果读取到的BUG既不是新提交的BUG,也不是激活的BUG,则判断该BUG是否为严重BUG(1、2级)且是否是未解决的BUG - // 读取解决方案那一列 - if ( bugList.get(i)[BugFilePosition.SOULVE_WAY].toString().equals("") ) { - return 1; - } else if (bugList.get(i)[BugFilePosition.SOULVE_WAY].toString().indexOf("延期") > -1) { - return 2; - } else { - return 0; - } - } - /* - * - * private String valueOf(XSSFCell cell) { String s; - * - * cell.getCellTypeEnum() == CellType.; - * - * //方法过期 if (cell.getCellType() == Cell.CELL_TYPE_STRING) { s = - * cell.getStringCellValue(); } - * - * else if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC) { if - * (HSSFDateUtil.isCellDateFormatted(cell)) { double d = - * cell.getNumericCellValue(); Date date = HSSFDateUtil.getJavaDate(d); s = - * new SimpleDateFormat("yyyy-MM-dd").format(date); } else { s = - * String.valueOf((int) cell.getNumericCellValue()); } } else if - * (cell.getCellType() == Cell.CELL_TYPE_BLANK) { s = ""; } else if - * (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { s = - * String.valueOf(cell.getBooleanCellValue()); } else if (cell.getCellType() - * == Cell.CELL_TYPE_ERROR) { s = ""; } else if (cell.getCellType() == - * Cell.CELL_TYPE_FORMULA) { s = cell.getCellFormula().toString(); } else { - * s = null; } - * - * return s; } - */ - - /** - * 用于记录BUG的编号、标题和等级信息 - * @author 彭宇琦 - */ - public class BugInformation { - public String bugID; - public String bugTitle; - public int bugLv; - public BugInformation(String bugID, String bugTitle, int bugLv) { - super(); - if ( bugID.indexOf(".") > -1 ) { - this.bugID = bugID.substring(0, bugID.indexOf(".")); - } - this.bugTitle = bugTitle; - this.bugLv = bugLv; - } - } -} diff --git a/src/main/java/pres/auxiliary/report/AutoTestReport.java b/src/main/java/pres/auxiliary/report/AutoTestReport.java deleted file mode 100644 index 3e6db3c..0000000 --- a/src/main/java/pres/auxiliary/report/AutoTestReport.java +++ /dev/null @@ -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 - * - * } - */ -} diff --git a/src/main/java/pres/auxiliary/report/BugFilePosition.java b/src/main/java/pres/auxiliary/report/BugFilePosition.java deleted file mode 100644 index fc4a163..0000000 --- a/src/main/java/pres/auxiliary/report/BugFilePosition.java +++ /dev/null @@ -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; - } - } -} diff --git a/src/main/java/pres/auxiliary/report/IncompatibleFileLayoutException.java b/src/main/java/pres/auxiliary/report/IncompatibleFileLayoutException.java deleted file mode 100644 index ae58fde..0000000 --- a/src/main/java/pres/auxiliary/report/IncompatibleFileLayoutException.java +++ /dev/null @@ -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; - -} diff --git a/src/main/java/pres/auxiliary/report/IncorrectBugVersionException.java b/src/main/java/pres/auxiliary/report/IncorrectBugVersionException.java deleted file mode 100644 index c7e66f8..0000000 --- a/src/main/java/pres/auxiliary/report/IncorrectBugVersionException.java +++ /dev/null @@ -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 自动生成的构造函数存根 - } - - -} diff --git a/src/main/java/pres/auxiliary/report/IncorrectGrammarException.java b/src/main/java/pres/auxiliary/report/IncorrectGrammarException.java deleted file mode 100644 index b0bb886..0000000 --- a/src/main/java/pres/auxiliary/report/IncorrectGrammarException.java +++ /dev/null @@ -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; -} diff --git a/src/main/java/pres/auxiliary/report/InvalidBugListFileSignException.java b/src/main/java/pres/auxiliary/report/InvalidBugListFileSignException.java deleted file mode 100644 index 27eefc7..0000000 --- a/src/main/java/pres/auxiliary/report/InvalidBugListFileSignException.java +++ /dev/null @@ -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 自动生成的构造函数存根 - } - - -} diff --git a/src/main/java/pres/auxiliary/report/ReportFactory.java b/src/main/java/pres/auxiliary/report/ReportFactory.java deleted file mode 100644 index 7bd2915..0000000 --- a/src/main/java/pres/auxiliary/report/ReportFactory.java +++ /dev/null @@ -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; - } - } -} diff --git a/src/main/java/pres/auxiliary/report/ReportInter.java b/src/main/java/pres/auxiliary/report/ReportInter.java deleted file mode 100644 index 4a901f7..0000000 --- a/src/main/java/pres/auxiliary/report/ReportInter.java +++ /dev/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汇总表,其返回的数组存储的信息如下表所示:
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
s[0]:项目名称s[1]:当前版本s[2]:1级BUG数量s[3]:2级BUG数量
s[4]:3级BUG数量s[5]:4级BUG数量s[6]:激活1级BUG数量s[7]:激活2级BUG数量
s[8]:激活3级BUG数量s[9]:激活4级BUG数量s[10]:未解决的1级BUG数量s[11]:未解决的2级BUG数量
s[12]:延期解决1级BUG数量s[13]:延期解决2级BUG数量
- * - * @param excel - * BUG汇总表 - * @param testDay - * 测试的天数 - * @return Bug汇总表中提取的信息 - * @throws IOException - */ - public abstract String[] readFile(File excel, int testDay) - throws IOException; -} \ No newline at end of file diff --git a/src/main/java/pres/auxiliary/report/TestReport.java b/src/main/java/pres/auxiliary/report/TestReport.java deleted file mode 100644 index 58b2c30..0000000 --- a/src/main/java/pres/auxiliary/report/TestReport.java +++ /dev/null @@ -1,1073 +0,0 @@ -package pres.auxiliary.report; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import javax.activation.DataHandler; -import javax.activation.FileDataSource; -import javax.mail.Message.RecipientType; -import javax.mail.MessagingException; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; - -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -/** - * 该类用于从禅道上导出的BUG列表,使用项目路径下Templet的模版文件(TestReportTemplet.docx),来生成测试报告, - * 支持压缩测试报告文件以及发送邮件到项目相关的人员(邮件功能需要配置项目路径下的ConfigurationFiles/ - * ReportConfigurationFile/TestReportConfiguration.xml文件) - * - * @author 彭宇琦 - */ -public class TestReport extends AbstractReport { - /** - * 用于存储邮件内容 - */ - private StringBuilder mail = new StringBuilder(""); - /** - * 设置配置文件存放的位置 - */ - public final String xml = "ConfigurationFiles/ReportConfigurationFile/TestReportConfiguration.xml"; - /** - * 设置禅道元素xpath文件存放位置 - */ - public final String xpath = "ConfigurationFiles/ReportConfigurationFile/ZendaoElementXpath.xml"; - /** - * 设置模版文件存放位置 - */ - public final String templet = "Templet\\TestReportTemplet.docx"; - - /** - * 存储项目的名称 - */ - private String projectName; - - /** - * 存储项目的版本(带项目名称) - */ - private String projectVersion; - - /** - * 该构造只用于创建对象 - */ - public TestReport() { - } - - /** - * 该构造方法用于设置测试报告保存位置 - * - * @param savePath - * 测试报告保存位置 - */ - public TestReport(String savePath) { - setSavePath(savePath); - } - - /** - * 该方法用于返回在发送测试报告邮件中正文的内容,不包括项目经理的名字等信息 - * - * @return 测试报告邮件中正文的内容 - */ - /* - public String getMailContent() { - return mail.toString(); - } - */ - - /** - * 用于根据项目名称或项目名的关键词来查询其项目的邮件发送人及收信人,注意,返回值是二维字符串数组, - * 其第一维表示收件人,第二维表示抄送人;收件人或抄送人返回的格式为:“姓名:邮箱”,如“张三:XX@qq.com” - * - * @param project - * 项目名称或项目名称关键词 - * @return 项目对应的邮件发送人及收信人 - */ - @SuppressWarnings("unchecked") - public String[][] getMailToAndCc(String project) { - // TODO 还是要添加空标签到返回的列表中,否则第一次的项目无法通过该方法获取收件人与抄送人 - // 用于存储收件人及抄送人 - String[][] ss = new String[2][]; - - // 读取配置好的XML文件 - Document dom = null; - try { - dom = new SAXReader().read(new File(xml)); - } catch (DocumentException e) { - e.printStackTrace(); - } - // 获取根节点 - Element root = dom.getRootElement(); - - // 存储合适的收件人标签对象 - Element to = null; - - // 循环,遍历所有的收件人标签中项目的名称,查看是否有与之对应的项目收件人,若查不到,则查找一个无“project”属性的收件人标签,若仍没有,则报错 - for (Element toTem : (List) root.element("mail") - .elements("to")) { - int i = 0; - // 判断当前遍历的标签是否包含project属性,不包含则暂时存储该标签,若整个遍历结束未找到对应的project,则该标签即为收件人标签 - if (toTem.attribute("project") == null) { - // 判断XML文件是否只存在一个project属性为空的cc标签,若存在多个,则抛出异常 - if (++i <= 1) { - to = toTem; - continue; - } else { - throw new IncorrectGrammarException("存在多个没有project属性的to标签"); - } - } - // 判断当前遍历标签中的project属性的值是否与传入的project参数对应,若对应,则存储该标签 - if (toTem.attributeValue("project").indexOf(project) > -1) { - to = toTem; - break; - } - } - - // 判断遍历后是否存在合适的to标签,不存在则抛出异常 - if (to == null) { - throw new IncorrectGrammarException("未找到相应项目的邮件接收人和抄送人"); - } - - // 用于拼接收件人及抄送人邮箱,由于收件人与抄送人都存在多个,所以不能直接使用使用setRecipient()方法 - StringBuilder toStr = new StringBuilder(); - StringBuilder ccStr = new StringBuilder(); - - // 遍历to标签下的所有收件人,写入到邮件,并存储该收件人的名字到mailContent中 - for (Element preson : (List) (to.elements())) { - // 判断当前收件人是否存在,不存在则添加收件人 - if (toStr.indexOf(preson.attributeValue("mail")) == -1) { - // 拼接收件人名字及邮箱 - toStr.append(preson.attributeValue("name") + ":" - + preson.attributeValue("mail") + ","); - } - } - - // 遍历cc标签,设置抄送人 - for (Element preson : (List) root.element("mail").element("cc") - .elements()) { - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(preson.attributeValue("mail")) == -1 - && toStr.indexOf(preson.attributeValue("mail")) == -1) { - ccStr.append(preson.attributeValue("name") + ":" - + preson.attributeValue("mail") + ","); - } - } - - // 再将项目组的测试人员邮箱设置为抄送人 - for (Element testPreson : (List) root.element("report") - .element("testperson").elements()) { - // 判断测试组成员是否参与测试,参与测试则设置其邮箱为抄送 - if (testPreson.attributeValue("participation") - .equalsIgnoreCase("true")) { - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(testPreson.attributeValue("mail")) == -1 - && toStr.indexOf( - testPreson.attributeValue("mail")) == -1) { - ccStr.append(testPreson.attributeValue("name") + ":" - + testPreson.attributeValue("mail") + ","); - } - } - } - // 添加自己 - ccStr.append(root.element("mail").attributeValue("name") + ":" - + root.element("mail").attributeValue("username")); - - ss[0] = toStr.toString().split("\\,"); - ss[1] = ccStr.toString().split("\\,"); - - return ss; - } - - /** - * 该方法用于完整创建一个测试报告,输入测试报告特有,自动化测试报告不能直接使用该方法 - * - * @param name - * 项目名称 - * @param version - * 版本号(注意,此处的版本号是包括项目名称的) - * @param time - * 测试开始时间 - * @param person - * 测试组参与人员 - * @param range - * 测试范围 - * @param purpose - * 测试目的 - * @param gist - * 测试依据 - * @param content - * 测试报告内容 - * @param accessory - * 附件名称 - * @return 邮件内容 - * @throws IOException - */ - public String createReport(String name, String version, String time, - String person, String range, String purpose, String gist, - String content, String accessory) throws IOException { - - // 将测试结果写入模版 - // 用于存储待替换的文本及文本的定位 - Map params = new HashMap(); - // 存储替换的标签以及替换的文本 - params.put("name", name); - params.put("version", version); - params.put("time", time); - params.put("purpose", purpose); - params.put("gist", gist); - params.put("person", person); - params.put("range", range); - params.put("accessory", accessory); - params.put("result", content); - - // 读取模版文件 - FileInputStream fip = new FileInputStream(templet); - // 使用POI中的读取word文件的方法 - XWPFDocument xd = new XWPFDocument(fip); - // 关闭读出流 - fip.close(); - - // 读取模版 - readeTemplet(xd, params); - - // 拼接邮件内容 - mail.append(content); - - // 判断是否打开文件夹,存在就自动弹出文件 - if (isOpenFolder()) { - java.awt.Desktop.getDesktop().open(new File(getSavePath())); - } - - // 打包测试报告 - compressReportFile(new File(getSavePath() + version + "版本测试报告")); - - // 删除从禅道上导出的BUG列表文件,参见Report类中bugListFile属性 - bugListFile.delete(); - - return mail.toString(); - } - - @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 { - // 读取配置文件的内容 - Document dom = null; - try { - dom = new SAXReader().read(new File(xml)); - } catch (DocumentException e) { - e.printStackTrace(); - return null; - } - // 获取测试报告中的内容 - Element content = dom.getRootElement().element("report") - .element("content"); - - // 用于存储测试输出及测试结果 - StringBuilder testResult = new StringBuilder(""); - - // 判断测试结果文件保存路径和测试结果文件名是否存在,若不存在则抛出UndefinedDirectoryException异常 - if ("".equals(getSavePath()) || "".equals(getFileName())) { - throw new UndefinedDirectoryException("未定义文件路径或者文件名,文件路径:" - + getSavePath() + ",文件名:" + getFileName()); - } - - // 用于存储测试时间 - StringBuilder time = new StringBuilder(); - // 判断是否需要修改测试时间,若不需要则自动计算,需要则直接读取 - if (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 - testDay)); - // 将得到的时间转换为Date进行返回 - d = calendar.getTime(); - // 存储测试开始时间 - time.append(new SimpleDateFormat("yyyy.MM.dd").format(d)); - - time.append("-"); - - d = new Date(); - time.append(new SimpleDateFormat("yyyy.MM.dd").format(d)); - // d.setDate(d.getDate() - testDay);//方法过时 - } else { - time.append(content.element("time").element("starttime").getText()); - time.append("-"); - time.append(content.element("time").element("endtime").getText()); - } - - // 读取配置文件中的测试目的 - StringBuilder purpose = new StringBuilder(); - @SuppressWarnings("unchecked") - List purposes = content.element("purpose") - .elements(); - // 获取测试目的 - for (int i = 0; i < purposes.size(); i++) { - purpose.append((i + 1) + "." + purposes.get(i).getText() + "\n"); - } - purpose.delete(purpose.lastIndexOf("\n"), purpose.length()); - - // 读取配置文件中的测试依据 - StringBuilder gist = new StringBuilder(); - @SuppressWarnings("unchecked") - List gists = content.element("gist") - .elements(); - // 获取测试目的 - for (int i = 0; i < gists.size(); i++) { - // 修改带${name}的 - if (gists.get(i).getText().indexOf("${name}") > -1) { - gist.append((i + 1) + "." + gists.get(i).getText() + "\n"); - gist.replace(gist.indexOf("$"), gist.indexOf("}") + 1, name); - } else { - gist.append((i + 1) + "." + gists.get(i).getText() + "\n"); - } - } - gist.delete(gist.lastIndexOf("\n"), gist.length()); - - // 编辑测试报告邮件中的内容 - mail.delete(0, mail.length()); - - mail.append("附件是"); - mail.append(name + version + "版本测试报告,"); - - if (activeOne != 0 || activeTwo != 0 || activeThree != 0 - || activeFour != 0) { - testResult.append("回归测试发现并激活" - + String.valueOf( - activeOne + activeTwo + activeThree + activeFour) - + "个Bug,其中"); - if (activeOne != 0) { - testResult.append("一级Bug有" + activeOne + "个,"); - } - if (activeTwo != 0) { - testResult.append("二级Bug有" + activeTwo + "个,"); - } - if (activeThree != 0) { - testResult.append("三级Bug有" + activeThree + "个,"); - } - if (activeFour != 0) { - testResult.append("四级Bug有" + activeFour + "个,"); - } - testResult.replace(testResult.lastIndexOf(","), - testResult.lastIndexOf(",") + 1, ";"); - } - testResult.append("新发现并提交" + String.valueOf(one + two + three + four) - + "个Bug,其中,"); - testResult.append("一级Bug有" + one + "个,"); - testResult.append("二级Bug有" + two + "个,"); - testResult.append("三级Bug有" + three + "个,"); - testResult.append("四级Bug有" + four + "个,"); - testResult.append("详情请查看禅道系统或者问题汇总中的Bug记录详情。"); - // 判断是否存在一级或二级的BUG,根据判断给出相应的文字结果 - if (one != 0 || two != 0 || activeOne != 0 || activeTwo != 0) { - testResult.append("由于该版本存在二级以上的Bug,根据测试依据软件测试通过准则,判定该版本测试结果为:不通过。\n"); - } else { - testResult.append("由于该版本未发现二级以上的Bug,根据测试依据软件测试通过准则,判定该版本测试结果为:通过。\n"); - } - - //若有严重的BUG存在,则获取其信息列表,之后将严重的BUG信息放入报告中 - if ( one != 0 || two != 0) { - List bugInformation = 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 ( noSulveOne != 0 || noSulveTwo != 0 || delayOne != 0 || delayTwo != 0 ) { - testResult.append("在往期版本中,发现存在未解决、延期处理的一、二级Bug,总数为" + (noSulveOne + noSulveTwo + delayOne + delayTwo) + "个,其中,"); - if ( noSulveOne != 0 ) { - testResult.append("未解决的一级Bug有" + noSulveOne + "个,"); - } - if ( noSulveTwo != 0 ) { - testResult.append("未解决二级Bug有" + noSulveTwo + "个,"); - } - if ( delayOne != 0 ) { - testResult.append("延期解决的一级Bug有" + delayOne + "个,"); - } - if ( delayTwo != 0 ) { - testResult.append("延期解决的二级Bug有" + delayTwo + "个,"); - } - testResult.append("望技术经理、开发人员及项目经理重视!\n"); - - } - - return createReport(name, (name + version), time.toString(), person, - range, purpose.toString(), gist.toString(), - testResult.toString(), accessory); - } - - @Override - public String createReport(File bugListFile, int testDay, String person, - String range) throws IOException { - // 判断测试结果文件保存路径和测试结果文件名是否存在,若不存在则抛出UndefinedDirectoryException异常 - if ("".equals(getSavePath())) { - throw new UndefinedDirectoryException("未定义文件路径或者文件名,文件路径:" - + getSavePath() + ",文件名:" + getFileName()); - } - - // 调用读取Bug列表的方法,并将存储其返回值 - String[] s = readFile(bugListFile, testDay); - - setFileName(s[0] + "Ver" + s[1] + "版本测试报告"); - - // bugListFile.delete(); - - // 存储项目名称及版本 - projectName = s[0]; - projectVersion = s[0] + "Ver" + s[1]; - - // 调用重载的方法,将得到的数组作为参数传入 - return createReport(s[0], ("Ver" + s[1]), testDay, person, range, - Integer.valueOf(s[6]), Integer.valueOf(s[7]), - Integer.valueOf(s[8]), Integer.valueOf(s[9]), - Integer.valueOf(s[2]), Integer.valueOf(s[3]), - Integer.valueOf(s[4]), Integer.valueOf(s[5]), - Integer.valueOf(s[10]), Integer.valueOf(s[11]),Integer.valueOf(s[12]),Integer.valueOf(s[13]), - ("附:" + s[0] + "Ver" + s[1] + "版本Bug汇总表.xlsx")); - } - - /** - * 该方法通过ConfigurationFiles/ReportConfigurationFile/ZendaoBasicInformation. - * xml配置文件中的信息来自动编写测试报告 - * - * @param isSandEMail - * 是否自动发送邮件 - * - * @param isPrintReport - * 是否打印测试报告 - * - * @throws DocumentException - * @throws InterruptedException - * @throws IOException - */ - public String AutoWriteReport(boolean isSandEMail, boolean isPrintReport) - throws DocumentException, InterruptedException, IOException { - // 定义读取xml文件的对象,用于取出基本配置 - Document dom = new SAXReader().read(new File(xml)); - - // 获取基本信息并存储 - 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"); - String range = dom.getRootElement().element("report") - .attributeValue("range"); - int testDay = Integer.valueOf( - dom.getRootElement().element("report").attributeValue("days")); - StringBuilder person = new StringBuilder(); - - // 对禅道进行操作 - operationZendao(firefoxDirectory, firefoxProfiles, url, username, - password, search, downloadFileName); - - // 添加参与测试的人员 - @SuppressWarnings("unchecked") - List l = dom.getRootElement().element("report") - .element("testperson").elements(); - for (Element e : l) { - if (e.attributeValue("participation").equalsIgnoreCase("true")) { - person.append(e.attributeValue("name") + "、"); - } - } - // 清除多余的符号 - person.delete(person.lastIndexOf("、"), person.lastIndexOf("、") + 1); - - // 进行读取csv文件的操作 - createReport( - new File(downloadSaveDirectory + downloadFileName + ".csv"), - testDay, person.toString(), range); - - // 发送邮件(若用户允许自动发送,则进行发送邮件的操作,其是否允许只能在调用AutoWriteReport()方法中传参设置,直接调用本方法时,默认为不发送) - String content = mail.toString(); - if (isSandEMail) { - try { - content = sandMail(mail.toString(), projectName, - (projectVersion + "版本测试报告"), range, new File( - getSavePath() + projectVersion + "版本测试报告.zip")); - - // 发送完邮件后压缩文件已无用处,则自动删除 - new File(getSavePath() + projectVersion + "版本测试报告.zip") - .delete(); - } catch (DocumentException e) { - e.printStackTrace(); - } catch (MessagingException e) { - e.printStackTrace(); - } - } - - // 根据传入的参数栏判断是否打印报告,若传入的打印机名称不对或者网络不通时会打印失败,此时不做处理 - if (isPrintReport) { - try { - printReport( - new File(getSavePath() + projectVersion + "版本测试报告\\" - + projectVersion + "版本测试报告.docx"), - dom.getRootElement().element("report") - .attributeValue("print_name")); - } catch (Exception e) { - } - } - - return content; - } - - /** - * 该方法用于发送邮件到相关的人员 - * - * @param reportContent - * 报告的内容 - * @param project - * 项目名称或关键词 - * @param title - * 邮件标题 - * @param attch - * 附件 - * @throws DocumentException - * @throws UnsupportedEncodingException - * @throws MessagingException - * @throws IOException - */ - @SuppressWarnings({ "unchecked" }) - public String sandMail(String reportContent, String project, String title, String range, - File attch) throws DocumentException, UnsupportedEncodingException, - MessagingException, IOException { - // 读取配置好的XML文件 - Document dom = new SAXReader().read(new File(xml)); - // 获取根节点 - Element root = dom.getRootElement(); - - // 获取发件邮箱的信息 - String mailUsername = root.element("mail").attributeValue("username"); - String mailPassword = root.element("mail").attributeValue("password"); - String mailSmtp = root.element("mail").attributeValue("smtp"); - - // 定义邮件的内容 - String mailContent = getMailContent(reportContent, project, title, range); - - // 创建参数配置, 用于连接邮件服务器的参数配置 - Properties props = new Properties(); - // 设置使用的协议(JavaMail规范要求) - props.setProperty("mail.transport.protocol", "smtp"); - // 设置发件人的邮箱的 SMTP服务器地址 - props.setProperty("mail.smtp.host", mailSmtp); - // 需要请求认证 - props.setProperty("mail.smtp.auth", "true"); - - // 设置邮箱端口 - final String smtpPort = "465"; - props.setProperty("mail.smtp.port", smtpPort); - props.setProperty("mail.smtp.socketFactory.class", - "javax.net.ssl.SSLSocketFactory"); - props.setProperty("mail.smtp.socketFactory.fallback", "false"); - props.setProperty("mail.smtp.socketFactory.port", smtpPort); - - // 根据配置创建会话对象, 用于和邮件服务器交互 - Session session = Session.getInstance(props); - // 设置为debug模式, 可以查看详细的发送 log,即在控制台打印日志,感觉用处不大 - // session.setDebug(true); - - // 创建邮件 - MimeMessage message = new MimeMessage(session); - - // 配置发件人及昵称(昵称为发件人姓名,以降低被认为是垃圾邮件的概率) - message.setFrom(new InternetAddress(mailUsername, - root.element("mail").attributeValue("name"))); - - // 存储合适的收件人标签对象 - Element to = null; - - // 循环,遍历所有的收件人标签中项目的名称,查看是否有与之对应的项目收件人,若查不到,则查找一个无“project”属性的收件人标签,若仍没有,则报错 - for (Element toTem : (List) root.element("mail") - .elements("to")) { - int i = 0; - // 判断当前遍历的标签是否包含project属性,不包含则暂时存储该标签,若整个遍历结束未找到对应的project,则该标签即为收件人标签 - if (toTem.attribute("project") == null) { - // 判断XML文件是否只存在一个project属性为空的cc标签,若存在多个,则抛出异常 - if (++i <= 1) { - to = toTem; - continue; - } else { - throw new IncorrectGrammarException("存在多个没有project属性的to标签"); - } - } - - // 判断当前遍历标签中的project属性的值是否与传入的project参数对应,若对应,则存储该标签 - if (toTem.attributeValue("project").indexOf(project) > -1) { - to = toTem; - break; - } - } - - // 判断遍历后是否存在合适的to标签,不存在则抛出异常 - if (to == null) { - throw new IncorrectGrammarException("未查找到合适的to标签"); - } - - // 判断选择的标签是否为无project属性的标签,若是,则赋予其project属性,以便下一次快捷访问 - if (to.attribute("project") == null) { - to.addAttribute("project", project); - // 使用dom4j的漂亮格式 - OutputFormat format = OutputFormat.createPrettyPrint(); - // 设置xml文件的编码方式 - format.setEncoding("GBK"); - // 写入xml - XMLWriter xmlWriter = new XMLWriter( - new FileOutputStream(new File(xml)), format); - - xmlWriter.write(dom); - xmlWriter.close(); - } - - // 用于拼接收件人及抄送人邮箱,由于收件人与抄送人都存在多个,所以不能直接使用使用setRecipient()方法 - StringBuilder toStr = new StringBuilder(); - StringBuilder ccStr = new StringBuilder(); - - // 设置多个收件人 - message.setRecipients(RecipientType.TO, - InternetAddress.parse(toStr.toString())); - - // 遍历cc标签,设置抄送人 - for (Element preson : (List) root.element("mail").element("cc") - .elements()) { - /* - * // 设置抄送人 message.setRecipient(MimeMessage.RecipientType.CC, new - * InternetAddress(preson.attributeValue("mail"), "", "UTF-8")); - */ - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(preson.attributeValue("mail")) == -1 - && toStr.indexOf(preson.attributeValue("mail")) == -1) { - ccStr.append(preson.attributeValue("mail") + ","); - } - } - // 再将项目组的测试人员邮箱设置为抄送人 - for (Element testPreson : (List) root.element("report") - .element("testperson").elements()) { - // 判断测试组成员是否参与测试,参与测试则设置其邮箱为抄送 - if (testPreson.attributeValue("participation") - .equalsIgnoreCase("true")) { - /* - * message.setRecipient(MimeMessage.RecipientType.CC, new - * InternetAddress(testPreson.attributeValue("mail"), "", - * "UTF-8")); - */ - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(testPreson.attributeValue("mail")) == -1 - && toStr.indexOf( - testPreson.attributeValue("mail")) == -1) { - ccStr.append(testPreson.attributeValue("mail") + ","); - } - } - } - // 再将自己拼接入抄送人中,以避免邮件无法发送 - ccStr.append(root.element("mail").attributeValue("username")); - // 设置多个抄送人 - message.setRecipients(RecipientType.CC, - InternetAddress.parse(ccStr.toString())); - - // 设置邮件主题 - message.setSubject(title); - - // 设置邮件正文,注意,其附件也属于正文内容,需要添加一个MimeMultipart对象才能将整个邮件内容添加进去,使用混合关系 - MimeMultipart msgMultipart = new MimeMultipart("mixed"); - - // 添加附件 - MimeBodyPart mailAttch = new MimeBodyPart(); - // 把文件,添加到附件中,DataHandler类表示源文件,FileDataSource类为文件处理器 - mailAttch.setDataHandler(new DataHandler(new FileDataSource(attch))); - // 设置附件名称,注意,文件名称不能太长,否则文件无法上传,甚至被退回的可能,所以只能写死为“report.zip” - mailAttch.setFileName("report.zip"); - // 将附件添加至msgMultipart中 - msgMultipart.addBodyPart(mailAttch); - - // 添加邮件正文 - MimeBodyPart mailText = new MimeBodyPart(); - - // 将正文添加至mailText中 - mailText.setContent(mailContent, "text/html;charset=GBK"); - // 将邮件正文添加至msgMultipart中 - msgMultipart.addBodyPart(mailText); - - // 将msgMultipart添加至邮件内容中 - message.setContent(msgMultipart); - - // 设置发件时间 - message.setSentDate(new Date()); - - // 保存设置 - message.saveChanges(); - - // 根据 Session 获取邮件传输对象 - Transport transport = session.getTransport(); - - // 使用邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与 message 中的发件人邮箱一致,否则报错 - transport.connect(mailUsername, mailPassword); - - // 发送邮件 - transport.sendMessage(message, message.getAllRecipients()); - - // 关闭连接 - transport.close(); - - return mailContent; - } - - /** - * 该方法用于返回在发送测试报告邮件中正文的内容,不包括项目经理的名字等信息 - * - * @param reportContent - * 报告的内容 - * @param project - * 项目名称或关键词 - * @param title - * 邮件标题 - * @param range - * 测试范围 - * @return 测试报告邮件中正文的内容 - * - * @throws DocumentException - * @throws UnsupportedEncodingException - * @throws MessagingException - * @throws IOException - */ - @SuppressWarnings("unchecked") - public String getMailContent(String reportContent, String project, String title, String range) throws DocumentException, UnsupportedEncodingException, - MessagingException, IOException { - // 读取配置好的XML文件 - Document dom = new SAXReader().read(new File(xml)); - // 获取根节点 - Element root = dom.getRootElement(); - - // 定义邮件的内容 - StringBuilder mailContent = new StringBuilder(); - - // 存储合适的收件人标签对象 - Element to = null; - - // 循环,遍历所有的收件人标签中项目的名称,查看是否有与之对应的项目收件人,若查不到,则查找一个无“project”属性的收件人标签,若仍没有,则报错 - for (Element toTem : (List) root.element("mail") - .elements("to")) { - int i = 0; - // 判断当前遍历的标签是否包含project属性,不包含则暂时存储该标签,若整个遍历结束未找到对应的project,则该标签即为收件人标签 - if (toTem.attribute("project") == null) { - // 判断XML文件是否只存在一个project属性为空的cc标签,若存在多个,则抛出异常 - if (++i <= 1) { - to = toTem; - continue; - } else { - throw new IncorrectGrammarException("存在多个没有project属性的to标签"); - } - } - - // 判断当前遍历标签中的project属性的值是否与传入的project参数对应,若对应,则存储该标签 - if (toTem.attributeValue("project").indexOf(project) > -1) { - to = toTem; - break; - } - } - - // 判断遍历后是否存在合适的to标签,不存在则抛出异常 - if (to == null) { - throw new IncorrectGrammarException("未查找到合适的to标签"); - } - - // 判断选择的标签是否为无project属性的标签,若是,则赋予其project属性,以便下一次快捷访问 - if (to.attribute("project") == null) { - to.addAttribute("project", project); - // 使用dom4j的漂亮格式 - OutputFormat format = OutputFormat.createPrettyPrint(); - // 设置xml文件的编码方式 - format.setEncoding("GBK"); - // 写入xml - XMLWriter xmlWriter = new XMLWriter( - new FileOutputStream(new File(xml)), format); - - xmlWriter.write(dom); - xmlWriter.close(); - } - - // 用于拼接收件人及抄送人邮箱,由于收件人与抄送人都存在多个,所以不能直接使用使用setRecipient()方法 - StringBuilder toStr = new StringBuilder(); - StringBuilder ccStr = new StringBuilder(); - - mailContent.append("

"); - // 遍历to标签下的所有收件人,写入到邮件,并存储该收件人的名字到mailContent中 - for (Element preson : (List) (to.elements())) { - // 判断当前收件人是否存在,不存在则添加收件人 - if (toStr.indexOf(preson.attributeValue("mail")) == -1) { - // 拼接邮箱地址 - toStr.append(preson.attributeValue("mail") + ","); - // 拼接收件人名称到邮件内容中 - mailContent.append(preson.attributeValue("name") + "、"); - } - } - - // 将邮件内容的最后一个顿号改为冒号 - mailContent.replace(mailContent.lastIndexOf("、"), - mailContent.lastIndexOf("、") + 1, ":"); - mailContent.append("

"); - - // 遍历cc标签,设置抄送人 - for (Element preson : (List) root.element("mail").element("cc") - .elements()) { - /* - * // 设置抄送人 message.setRecipient(MimeMessage.RecipientType.CC, new - * InternetAddress(preson.attributeValue("mail"), "", "UTF-8")); - */ - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(preson.attributeValue("mail")) == -1 - && toStr.indexOf(preson.attributeValue("mail")) == -1) { - ccStr.append(preson.attributeValue("mail") + ","); - } - } - // 再将项目组的测试人员邮箱设置为抄送人 - for (Element testPreson : (List) root.element("report") - .element("testperson").elements()) { - // 判断测试组成员是否参与测试,参与测试则设置其邮箱为抄送 - if (testPreson.attributeValue("participation") - .equalsIgnoreCase("true")) { - /* - * message.setRecipient(MimeMessage.RecipientType.CC, new - * InternetAddress(testPreson.attributeValue("mail"), "", - * "UTF-8")); - */ - // 判断抄送人是否存在或者存在于收件人之中,不存在,则添加该抄送 - if (ccStr.indexOf(testPreson.attributeValue("mail")) == -1 - && toStr.indexOf( - testPreson.attributeValue("mail")) == -1) { - ccStr.append(testPreson.attributeValue("mail") + ","); - } - } - } - // 再将自己拼接入抄送人中,以避免邮件无法发送 - ccStr.append(root.element("mail").attributeValue("username")); - - // 添加测试范围至邮箱正文中 - mailContent.append("

该版本的测试范围为:" + range + "

"); - - // 判断测试报告是否有换行内容,若有,则按照换行符分割 - if (reportContent.indexOf("\n") > -1) { - boolean createTable = false; - // 分割字符串 - String[] ss = reportContent.toString().split("\\n"); - for (int i = 0; i < ss.length; i++) { - if ( ss[i].indexOf("●") > -1 ) { - if ( !createTable ) { - createTable = true; - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - } - - if ( createTable ) { - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - mailContent.append(""); - continue; - } - } else { - if ( createTable ) { - mailContent.append("
"); - mailContent.append("Bug标题"); - mailContent.append(""); - mailContent.append("Bug等级"); - mailContent.append(""); - mailContent.append("Bug编号"); - mailContent.append("
"); - mailContent.append(ss[i].substring(ss[i].indexOf("●") + "●".length(), ss[i].indexOf("("))); - mailContent.append(""); - mailContent.append(ss[i].substring(ss[i].indexOf("(") + "(".length(), ss[i].indexOf("(") + "(".length() + 1)); - mailContent.append(""); - mailContent.append(ss[i].substring(ss[i].lastIndexOf(":") + ":".length(), ss[i].length() - 1)); - mailContent.append("
"); - createTable = false; - } - } - - // 添加剩余的邮件正文到mailContent中 - mailContent.append("

"); - mailContent.append(ss[i] + "

"); - } - } else { - // 添加剩余的邮件正文到mailContent中 - mailContent.append("

"); - mailContent.append(reportContent + "

"); - } - - // 判断是否有邮件的追加内容,若有则添加邮件追加内容 - if (root.element("mail").element("addcontent") != null || !root - .element("mail").element("addcontent").getText().equals("")) { - mailContent.append("

"); - mailContent - .append(root.element("mail").element("addcontent").getText() - + "

"); - } - - // 读取写信人的名字 - mailContent.append("

"); - mailContent.append( - "软件部品控科:" + root.element("mail").attributeValue("name")); - mailContent.append("

"); - - return mailContent.toString(); - } - - /** - * 该方法用于将测试报告文件夹及其所有的文件压缩成压缩 - * - * @param reportFolder - * 待压缩的文件夹对象 - * @throws IOException - */ - public void compressReportFile(File reportFolder) throws IOException { - // 获取测试报告文件夹中所有的文件 - File[] fileList = reportFolder.listFiles(); - // 创建压缩文件流对象 - ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream( - new FileOutputStream(new File(reportFolder.getParent() + "\\" - + reportFolder.getName() + ".zip")))); - // 定义缓存变量 - byte[] bufs = new byte[1024 * 10]; - // 循环,将文件夹中的文件全部写入到压缩文件中 - for (int i = -1; i < fileList.length; i++) { - // -1的作用:用于在压缩文件中添加根目录文件夹 - if (i == -1) { - // 压缩文件夹的方法 - zos.putNextEntry(new ZipEntry(reportFolder.getName() + "/")); - continue; - } - - // 创建ZIP实体,并添加进压缩包 - zos.putNextEntry(new ZipEntry( - reportFolder.getName() + "/" + fileList[i].getName())); - FileInputStream fis = new FileInputStream(fileList[i]); - BufferedInputStream bis = new BufferedInputStream(fis, 1024 * 10); - int read = 0; - while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) { - zos.write(bufs, 0, read); - } - - bis.close(); - } - zos.close(); - } - - /** - * 用于自动在禅道上导出BUG汇总表 - * - * @param firefoxDirectory - * @param firefoxProfiles - * @param url - * @param username - * @param password - * @param search - * @param downloadFileName - * @throws InterruptedException - */ - public void operationZendao(String firefoxDirectory, String firefoxProfiles, - String url, String username, String password, String search, - String downloadFileName) throws InterruptedException { - // 定义浏览器对象,自动登录禅道进行导出BUG汇总表的工作 - WebDriver d = new FirefoxBrower(firefoxDirectory, firefoxProfiles, url) - .getDriver(); - // 定义Control对象,读取禅道元素定位信息配置文件 - Event event = Event.newInstance(d); - event.setXmlFile(new File(xpath)); - XmlLocation r = new XmlLocation(new File(xpath)); - // 操作浏览器 - event.getTextEvent().input("用户名", username); - event.getTextEvent().input("密码", password); - event.getClickEvent().click("登录"); - event.getClickEvent().click("测试"); - event.getClickEvent().click("Bug"); - event.getClickEvent().click("项目下拉框"); - - // 由于禅道的项目搜索机制与其他页面不同,即使搜索了其
    标签下也显示所有的
  • ,故不能通过搜索后获取第一个元素来对搜索到的项目进行定位 - List l = null; - while (true) { - l = d.findElements(r.getBy("项目选项", ByType.XPATH)); - if (l.size() != 0) { - break; - } else { - Thread.sleep(100); - } - } - for (WebElement e : l) { - if (e.getText().indexOf(search) > -1) { - e.click(); - break; - } - } - event.getClickEvent().click("所有"); - - event.getClickEvent().click("ID"); - // 获取点击ID排序前后第一条BUG的ID号,以便判断当前是按照什么规则排序 - int before = Integer.valueOf(event.getTextEvent().getText("第一条Bug的ID").getStringValve()); - event.getClickEvent().click("ID"); - int after = Integer.valueOf(event.getTextEvent().getText("第一条Bug的ID").getStringValve()); - // 判断按ID排序前后,其第一条BUG的ID值是否是前比后大,若前比后大,则说明当前是升序,则应再点击一次ID,按降序排 - if (before > after) { - event.getClickEvent().click("ID"); - } - event.getClickEvent().click("导出"); - event.getClickEvent().click("导出数据"); - event.switchFrame("导出数据窗口"); - event.getTextEvent().input("文件名", downloadFileName); - event.getSelectEvent().select("文件格式下拉框", 0); - event.getSelectEvent().select("编码格式下拉框", 1); - event.getSelectEvent().select("记录下拉框", 0); - // 禅道的导出按钮无法点击,故需要通过提交表单的方法来导出 - d.findElement(r.getBy("导出数据表单", ByType.XPATH)).submit(); - d.close(); - } -} diff --git a/src/main/java/pres/auxiliary/report/ui/SandMailFrame.java b/src/main/java/pres/auxiliary/report/ui/SandMailFrame.java deleted file mode 100644 index 0a32ff7..0000000 --- a/src/main/java/pres/auxiliary/report/ui/SandMailFrame.java +++ /dev/null @@ -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); - } -} diff --git a/src/main/java/pres/auxiliary/report/ui/TestReportFrame.java b/src/main/java/pres/auxiliary/report/ui/TestReportFrame.java deleted file mode 100644 index ab9be7a..0000000 --- a/src/main/java/pres/auxiliary/report/ui/TestReportFrame.java +++ /dev/null @@ -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 = 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()); - } -} diff --git a/src/main/java/pres/auxiliary/report/ui/TestReportMainFrame.java b/src/main/java/pres/auxiliary/report/ui/TestReportMainFrame.java deleted file mode 100644 index 03460f0..0000000 --- a/src/main/java/pres/auxiliary/report/ui/TestReportMainFrame.java +++ /dev/null @@ -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"; - - /** - * 存储测试报告中的所有内容,以下是存储的信息:
    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    s[0]:项目名称s[1]:当前版本s[2]:1级BUG数量s[3]:2级BUG数量
    s[4]:3级BUG数量s[5]:4级BUG数量s[6]:激活1级BUG数量s[7]:激活2级BUG数量
    s[8]:激活3级BUG数量s[9]:激活4级BUG数量s[10]:未解决的1级BUG数量s[11]:未解决的2级BUG数量
    s[12]:延期解决的1级BUG数量s[13]:延期解决的2级BUG数量s[14]:测试开始时间s[15]:测试结束时间
    s[16]:测试范围s[17]:测试人员s[18]:测试目的s[19]:测试依据
    - *
    - * 千万不要随意改动顺序,需要添加则向下加,不要覆盖前面的!否则主界面会有BUG! - * - */ - 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 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 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 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(); - } - }); - } -} diff --git a/src/main/java/pres/auxiliary/report/ui/TestReportUI.java b/src/main/java/pres/auxiliary/report/ui/TestReportUI.java deleted file mode 100644 index a37e1bd..0000000 --- a/src/main/java/pres/auxiliary/report/ui/TestReportUI.java +++ /dev/null @@ -1,26 +0,0 @@ -package pres.auxiliary.report.ui; - -import javax.swing.UIManager; - -/** - *

    文件名:TestReportUI.java

    - *

    用途:用于设置界面的样式,并初始化测试报告UI界面

    - *

    编码时间:2018年12月19日 上午9:27:20

    - * @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(); - } -} diff --git a/src/main/java/pres/auxiliary/tool/data/Condition.java b/src/main/java/pres/auxiliary/tool/data/Condition.java deleted file mode 100644 index 87fd2e9..0000000 --- a/src/main/java/pres/auxiliary/tool/data/Condition.java +++ /dev/null @@ -1,23 +0,0 @@ -package pres.auxiliary.tool.data; - -/** - *

    文件名:Condition.java

    - *

    用途:定义了条件类应包含的方法

    - *

    编码时间:2020年1月7日上午8:32:28

    - *

    修改时间:2020年1月7日上午8:32:28

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - * @param 继承Condition类的条件类 - */ -public abstract class Condition> { - /** - * 用于判断传入的数据是否满足相应的判断条件 - * @param 相应的条件类对象 - * @param data 数据 - * @param condition 条件类对象 - * @return 是否满足相应的判断条件 - */ - public abstract boolean judgeData(String data, T condition); -} diff --git a/src/main/java/pres/auxiliary/tool/data/FilterData.java b/src/main/java/pres/auxiliary/tool/data/FilterData.java deleted file mode 100644 index b01147d..0000000 --- a/src/main/java/pres/auxiliary/tool/data/FilterData.java +++ /dev/null @@ -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 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 filterText(List 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; - } -} diff --git a/src/main/java/pres/auxiliary/tool/data/GroupNotFoundException.java b/src/main/java/pres/auxiliary/tool/data/GroupNotFoundException.java deleted file mode 100644 index 7df894f..0000000 --- a/src/main/java/pres/auxiliary/tool/data/GroupNotFoundException.java +++ /dev/null @@ -1,38 +0,0 @@ -package pres.auxiliary.tool.data; - -/** - *

    文件名:GroupNotFindException.java

    - *

    用途:当条件组名不存在时抛出的异常

    - *

    编码时间:2020年1月9日上午8:57:41

    - *

    修改时间:2020年1月9日上午8:57:41

    - * @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); - } - -} diff --git a/src/main/java/pres/auxiliary/tool/data/Logic.java b/src/main/java/pres/auxiliary/tool/data/Logic.java deleted file mode 100644 index f52ee54..0000000 --- a/src/main/java/pres/auxiliary/tool/data/Logic.java +++ /dev/null @@ -1,232 +0,0 @@ -package pres.auxiliary.tool.data; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - *

    文件名:Condition.java

    - *

    用途:该类用于对文本的筛选条件进行编辑,可编辑的条件包含字符串、时间及数字

    - *

    编码时间:2020年1月2日上午7:48:53

    - *

    修改时间:2020年1月2日上午7:48:53

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ -public class Logic { - /** - * 用于标记对信息的分隔 - */ - private final String GROUP_SIGN = "group="; - - /** - * 表示逻辑的入口 - */ - private String mainGroup = ""; - - /** - * 存储条件组 - */ - private HashMap 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); - } - - /** - *

    文件名:Logic.java

    - *

    用途:用于存放条件的组合,包含对条件的增删改查的操作

    - *

    编码时间:2020年1月9日上午7:49:37

    - *

    修改时间:2020年1月9日上午7:49:37

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ - class ConditionGroup { - /** - * 用于对条件进行取反的标记 - */ - private final String NOT = "-"; - - /** - * 存储条件,使用字符串进行存储,其条件类返回的条件也必须是字符串 - */ - private ArrayList conditions = new ArrayList<>(); - /** - * 存储条件间的关系 - */ - private ArrayList 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∧q∨a”(p、q、a均为条件,p为根条件) - *

      - *
    • 删除条件p时,则逻辑变为:“q∨a”
    • - *
    • 删除条件q时,则逻辑变为:“p∨a”
    • - *
    - *

    - * @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 getConditions() { - return conditions; - } - - /** - * 返回关系集合 - * @return 关系集合 - */ - public ArrayList getRelations() { - return relations; - } - } -} diff --git a/src/main/java/pres/auxiliary/tool/data/NumberCondition.java b/src/main/java/pres/auxiliary/tool/data/NumberCondition.java deleted file mode 100644 index f7080b3..0000000 --- a/src/main/java/pres/auxiliary/tool/data/NumberCondition.java +++ /dev/null @@ -1,11 +0,0 @@ -package pres.auxiliary.tool.data; - -public class NumberCondition extends Condition { - @Override - public boolean judgeData(String data, NumberCondition condition) { - // TODO Auto-generated method stub - return false; - } - - -} diff --git a/src/main/java/pres/auxiliary/tool/data/RelationType.java b/src/main/java/pres/auxiliary/tool/data/RelationType.java deleted file mode 100644 index 882e714..0000000 --- a/src/main/java/pres/auxiliary/tool/data/RelationType.java +++ /dev/null @@ -1,15 +0,0 @@ -package pres.auxiliary.tool.data; - -/** - *

    文件名:Relation.java

    - *

    用途:定义添加条件间关系的枚举类,包括“或”(OR)与“且”(AND)

    - *

    编码时间:2020年1月2日上午8:18:09

    - *

    修改时间:2020年1月2日上午8:18:09

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ -public enum RelationType { - OR, AND; -} diff --git a/src/main/java/pres/auxiliary/tool/data/RootConditionNotFoundException.java b/src/main/java/pres/auxiliary/tool/data/RootConditionNotFoundException.java deleted file mode 100644 index f9b2b2b..0000000 --- a/src/main/java/pres/auxiliary/tool/data/RootConditionNotFoundException.java +++ /dev/null @@ -1,43 +0,0 @@ -package pres.auxiliary.tool.data; - -/** - *

    文件名:RootConditionNotFindException.java

    - *

    用途:当条件组未添加根条件时抛出的异常

    - *

    编码时间:2020年1月8日下午8:45:15

    - *

    修改时间:2020年1月8日下午8:45:15

    - * @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 - } - -} diff --git a/src/main/java/pres/auxiliary/tool/file/DisposeFile.java b/src/main/java/pres/auxiliary/tool/file/DisposeFile.java index 8061cae..3b31ad4 100644 --- a/src/main/java/pres/auxiliary/tool/file/DisposeFile.java +++ b/src/main/java/pres/auxiliary/tool/file/DisposeFile.java @@ -4,8 +4,6 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import pres.auxiliary.tool.controller.ReadFile; - /** *

    文件名:DisposeFile.java

    *

    用途:用于满足日常中对文本文件的处理

    diff --git a/src/main/java/pres/auxiliary/tool/controller/ReadFile.java b/src/main/java/pres/auxiliary/tool/file/ReadFile.java similarity index 95% rename from src/main/java/pres/auxiliary/tool/controller/ReadFile.java rename to src/main/java/pres/auxiliary/tool/file/ReadFile.java index a5cb452..c6db5ba 100644 --- a/src/main/java/pres/auxiliary/tool/controller/ReadFile.java +++ b/src/main/java/pres/auxiliary/tool/file/ReadFile.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.controller; +package pres.auxiliary.tool.file; import java.io.File; import java.io.FileInputStream; diff --git a/src/main/java/pres/auxiliary/tool/randomstring/IdCardType.java b/src/main/java/pres/auxiliary/tool/randomstring/IdCardType.java deleted file mode 100644 index 1df2cbd..0000000 --- a/src/main/java/pres/auxiliary/tool/randomstring/IdCardType.java +++ /dev/null @@ -1,5 +0,0 @@ -package pres.auxiliary.tool.randomstring; - -public enum IdCardType { - -} diff --git a/src/main/java/pres/auxiliary/tool/randomstring/CarLicecenType.java b/src/main/java/pres/auxiliary/tool/string/CarLicecenType.java similarity index 80% rename from src/main/java/pres/auxiliary/tool/randomstring/CarLicecenType.java rename to src/main/java/pres/auxiliary/tool/string/CarLicecenType.java index a3e5050..ba7d000 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/CarLicecenType.java +++ b/src/main/java/pres/auxiliary/tool/string/CarLicecenType.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; /** * 该枚举定义了部分车牌的样式 diff --git a/src/main/java/pres/auxiliary/tool/string/IdCardType.java b/src/main/java/pres/auxiliary/tool/string/IdCardType.java new file mode 100644 index 0000000..194767c --- /dev/null +++ b/src/main/java/pres/auxiliary/tool/string/IdCardType.java @@ -0,0 +1,5 @@ +package pres.auxiliary.tool.string; + +public enum IdCardType { + +} diff --git a/src/main/java/pres/auxiliary/tool/randomstring/IllegalStringLengthException.java b/src/main/java/pres/auxiliary/tool/string/IllegalStringLengthException.java similarity index 88% rename from src/main/java/pres/auxiliary/tool/randomstring/IllegalStringLengthException.java rename to src/main/java/pres/auxiliary/tool/string/IllegalStringLengthException.java index 083c56c..7c9a4ca 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/IllegalStringLengthException.java +++ b/src/main/java/pres/auxiliary/tool/string/IllegalStringLengthException.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; public class IllegalStringLengthException extends RuntimeException { diff --git a/src/main/java/pres/auxiliary/tool/randomstring/MobleNumberType.java b/src/main/java/pres/auxiliary/tool/string/MobleNumberType.java similarity index 93% rename from src/main/java/pres/auxiliary/tool/randomstring/MobleNumberType.java rename to src/main/java/pres/auxiliary/tool/string/MobleNumberType.java index ee6a9ca..68b3464 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/MobleNumberType.java +++ b/src/main/java/pres/auxiliary/tool/string/MobleNumberType.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/pres/auxiliary/tool/randomstring/PhoneType.java b/src/main/java/pres/auxiliary/tool/string/PhoneType.java similarity index 74% rename from src/main/java/pres/auxiliary/tool/randomstring/PhoneType.java rename to src/main/java/pres/auxiliary/tool/string/PhoneType.java index 483b349..d563fbd 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/PhoneType.java +++ b/src/main/java/pres/auxiliary/tool/string/PhoneType.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; /** * 该枚举用于表示电话号码的类型 diff --git a/src/main/java/pres/auxiliary/tool/randomstring/PresetString.java b/src/main/java/pres/auxiliary/tool/string/PresetString.java similarity index 95% rename from src/main/java/pres/auxiliary/tool/randomstring/PresetString.java rename to src/main/java/pres/auxiliary/tool/string/PresetString.java index f83d5f8..d669e3c 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/PresetString.java +++ b/src/main/java/pres/auxiliary/tool/string/PresetString.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; import java.util.ArrayList; import java.util.Random; diff --git a/src/main/java/pres/auxiliary/tool/randomstring/RandomString.java b/src/main/java/pres/auxiliary/tool/string/RandomString.java similarity index 97% rename from src/main/java/pres/auxiliary/tool/randomstring/RandomString.java rename to src/main/java/pres/auxiliary/tool/string/RandomString.java index 8030ed8..53a448d 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/RandomString.java +++ b/src/main/java/pres/auxiliary/tool/string/RandomString.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; import java.util.Random; diff --git a/src/main/java/pres/auxiliary/tool/randomstring/RandomWord.java b/src/main/java/pres/auxiliary/tool/string/RandomWord.java similarity index 95% rename from src/main/java/pres/auxiliary/tool/randomstring/RandomWord.java rename to src/main/java/pres/auxiliary/tool/string/RandomWord.java index 3a238f6..a846d5c 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/RandomWord.java +++ b/src/main/java/pres/auxiliary/tool/string/RandomWord.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/pres/auxiliary/tool/randomstring/RegionType.java b/src/main/java/pres/auxiliary/tool/string/RegionType.java similarity index 92% rename from src/main/java/pres/auxiliary/tool/randomstring/RegionType.java rename to src/main/java/pres/auxiliary/tool/string/RegionType.java index d9a11b0..81d5b5e 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/RegionType.java +++ b/src/main/java/pres/auxiliary/tool/string/RegionType.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; public enum RegionType { /** diff --git a/src/main/java/pres/auxiliary/tool/randomstring/StringMode.java b/src/main/java/pres/auxiliary/tool/string/StringMode.java similarity index 97% rename from src/main/java/pres/auxiliary/tool/randomstring/StringMode.java rename to src/main/java/pres/auxiliary/tool/string/StringMode.java index c7117a5..c907d0d 100644 --- a/src/main/java/pres/auxiliary/tool/randomstring/StringMode.java +++ b/src/main/java/pres/auxiliary/tool/string/StringMode.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.randomstring; +package pres.auxiliary.tool.string; /** * 该枚举规定了产生随机字符串时所需要的模型 diff --git a/src/main/java/pres/auxiliary/tool/ui/control/AutoNumberJTextArea.java b/src/main/java/pres/auxiliary/tool/ui/control/AutoNumberJTextArea.java deleted file mode 100644 index f5b893d..0000000 --- a/src/main/java/pres/auxiliary/tool/ui/control/AutoNumberJTextArea.java +++ /dev/null @@ -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; - } - } - } -} diff --git a/src/main/java/pres/auxiliary/tool/ui/control/InputDoSearchComboBox.java b/src/main/java/pres/auxiliary/tool/ui/control/InputDoSearchComboBox.java deleted file mode 100644 index 89223fa..0000000 --- a/src/main/java/pres/auxiliary/tool/ui/control/InputDoSearchComboBox.java +++ /dev/null @@ -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; - - /** - * 创建一个 JFilterComboBox, - * 其项取自现有的 ComboBoxModel。 - * 由于提供了 ComboBoxModel, - * 使用此构造方法创建的组合框不创建默认组合框模型, - * 这可能影响插入、移除和添加方法的行为方式。 - * @param aModel - 提供显示的项列表的 ComboBoxModel - */ - @SuppressWarnings("unchecked") - public InputDoSearchComboBox(ComboBoxModel aModel) { - super(aModel); - initialize(); - } - - /** - * 创建包含指定数组中的元素的 JFilterComboBox。 - * 默认情况下,选择数组中的第一项(因而也选择了该项的数据模型)。 - * @param items - 要插入到组合框的对象数组 - */ - @SuppressWarnings("unchecked") - public InputDoSearchComboBox(final Object items[]) { - super(items); - initialize(); - } - - /** - * 创建包含指定 Vector 中的元素的 JFilterComboBox。 - * 默认情况下,选择数组中的第一项(因而也选择了该项的数据模型)。 - * @param items - 要插入到组合框的向量数组 - */ - @SuppressWarnings("unchecked") - public InputDoSearchComboBox(Vector items) { - super(items); - initialize(); - } - - /** - * 创建具有默认数据模型的 JFilterComboBox。 - * 默认的数据模型为空对象列表。使用 addItem 添加项。 - * 默认情况下,选择数据模型中的第一项。 - */ - 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(); - } - } - - } -} diff --git a/src/main/java/pres/auxiliary/work/selenium/datadriven/Functions.java b/src/main/java/pres/auxiliary/work/selenium/datadriven/Functions.java index 225c7cc..5eabf26 100644 --- a/src/main/java/pres/auxiliary/work/selenium/datadriven/Functions.java +++ b/src/main/java/pres/auxiliary/work/selenium/datadriven/Functions.java @@ -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; /** *

    文件名:Functions.java

    diff --git a/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java b/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java deleted file mode 100644 index d4feb7f..0000000 --- a/src/main/java/pres/auxiliary/work/selenium/element/NoSuchWindownException.java +++ /dev/null @@ -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); - } - - -} diff --git a/src/main/java/pres/auxiliary/work/selenium/event/AssertEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/AssertEvent.java index d88a30b..003bedb 100644 --- a/src/main/java/pres/auxiliary/work/selenium/event/AssertEvent.java +++ b/src/main/java/pres/auxiliary/work/selenium/event/AssertEvent.java @@ -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 断言结果 */ diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java new file mode 100644 index 0000000..c5edc5c --- /dev/null +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java @@ -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; + +/** + *

    文件名:OperateDataTable.java

    + *

    用途: + * 提供对数据表格进行基本操作的事件,包括对数据列表的翻页、跳页、获取等操作,以简化部分操作的代码 + *

    + *

    编码时间:2020年11月17日上午7:58:40

    + *

    修改时间:2020年11月17日上午7:58:40

    + * @author 彭宇琦 + * @version Ver1.0 + * @since JDK 1.8 + * + */ +public class DataTableEvent extends AbstractEvent { + /** + * 用于进行点击事件 + */ + private ClickEvent clickEvent; + /** + * 用于进行文本事件 + */ + private TextEvent textEvent; + /** + * 用于进行断言事件 + */ + private AssertEvent assertEvent; + + /** + * 用于存储当前的列表元素 + */ + protected ArrayList 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; + } + + /** + *

    + * 获取指定的一行元素,下标允许传入负数,表示从后向前遍历,具体遍历逻辑 + * 可参考{@link DataListBy#getElement(int)}方法。 + *

    + *

    + * 注意:下标将按照元素列长度进行计算,若下标的绝对值大于元素列长度,且下标为正数,则 + * 获取最后一行元素;反之,则获取第一行元素。元素列个数可参考{@link #size()}方法 + *

    + * + * @param rowIndex 需要获取的行下标 + * @return 指定行的元素集合 + */ + public ArrayList getRowElement(int rowIndex) { + //根据下标,获取元素,并进行存储 + ArrayList 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 oldElementList, ArrayList 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 oldElementList = new ArrayList<>(); + if (!tableList.isEmpty()) { + //获取第一行元素 + oldElementList = getRowElement(1); + } + + //执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作 + if (action.getAsBoolean()) { + //获取操作后的第一行元素 + ArrayList newElementList = new ArrayList<>(); + if (!tableList.isEmpty()) { + //获取第一行元素 + newElementList = getRowElement(1); + } + + //断言元素,并返回结果 + return assertDataChange(oldElementList, newElementList); + } else { + return false; + } + } + + /** + *

    文件名:DataTableEvent.java

    + *

    用途: + * 若元素列表无法添加时抛出的异常 + *

    + *

    编码时间:2020年11月19日下午8:26:49

    + *

    修改时间:2020年11月19日下午8:26:49

    + * @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); + } + + } +} diff --git a/src/main/java/pres/auxiliary/work/selenium/tool/Log_Old.java b/src/main/java/pres/auxiliary/work/selenium/tool/Log_Old.java deleted file mode 100644 index 6e7b3ac..0000000 --- a/src/main/java/pres/auxiliary/work/selenium/tool/Log_Old.java +++ /dev/null @@ -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; - -/** - *

    文件名:Log.java

    - *

    用途:用于在txt文件中生成自动化测试相关的日志,亦可指定输出的内容

    - *

    编码时间:2019年6月1日上午11:34:54

    - *

    修改时间:2019年10月6日下午6:03:39

    - * @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; - - /** - * 用于按默认方式建文件保存位置及文件名称
    - * 默认位置为:C:\\AutoTestting\\TestResults\\
    - * 默认文件名为(不带后缀):TestResults - */ - public Log_Old() { - } - - /** - * 用于按指定的路径以及默认的文件名保存测试结果文件
    - * 默认文件名为(不带后缀):Image
    - * 注意,传入的文件路径可为相对路径,也可为绝对路径,若路径不符合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(); - } - -} diff --git a/src/main/java/pres/auxiliary/work/selenium/tool/RecordTool.java b/src/main/java/pres/auxiliary/work/selenium/tool/RecordTool.java deleted file mode 100644 index dbee629..0000000 --- a/src/main/java/pres/auxiliary/work/selenium/tool/RecordTool.java +++ /dev/null @@ -1,1322 +0,0 @@ -package pres.auxiliary.work.selenium.tool; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Set; -import java.util.UUID; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.openqa.selenium.WebDriverException; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -import cn.hutool.core.io.FileUtil; - -/** - *

    - * 文件名:RecordTool.java - *

    - *

    - * 用途:用于在自动化测试中对每个事件(操作)进行自动记录的工具,类中提供默认的工具类对象, - * 只需要传入日志存放文件夹,即可进行对步骤的说明进行自动记录。可通过类中提供的开关,以判断是否开始自动记录。 - *

    - *

    - * 需要注意的是,当我们需要对某个记录工具类进行详细设置的时候,可以使用类中的get方法,将记录工具类返回后后,对该类进行单独设置。 - * 例如,当使用截图工具Screenshot类时,需要对该类设置其WebDriver对象,否则报错,此时,可按照以下方法进行设置:
    - * RecordStep.getScreenshot().setDriver(driver); - *

    - *

    - * 编码时间:2019年9月7日下午3:30:39 - *

    - *

    - * 修改时间:2019年9月7日下午3:30:39 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ -public class RecordTool { - //TODO 路径相关 - /** - * 在未设置文件保存路径的情况下,默认提供一个保存路径 - */ - private static final String DEFAULT_FILE_PATH = "Result/RunRecord/"; - /** - * 指向Xmind相关的文件的模板位置 - */ - private static final String XMIND_TEMJPLET_FILE_PATH = "Templet/XMindTemplate/"; - - //TODO 记录类对象相关 - /** - * Log类对象,默认构造 - */ - private static Log_Old log = new Log_Old(DEFAULT_FILE_PATH); - /** - * Record类对象,默认构造 - */ - private static ExcelRecord_Old record = new ExcelRecord_Old(DEFAULT_FILE_PATH); - /** - * Screenshot类对象,默认构造 - */ - private static Screenshot screenshot = new Screenshot(DEFAULT_FILE_PATH); - - /** - * 用于存储log原始的存放文件夹路径 - */ - private static String logSavePath = ""; - /** - * 用于存储record原始的存放文件夹路径 - */ - private static String recordSavePath = ""; - /** - * 用于存储screenshot原始的存放文件夹路径 - */ - private static String screenshotSavePath = ""; - - //TODO 容器相关 - /** - * 用于存储当前需要使用的记录工具类,初始化为将所有的记录工具都开启 - */ - private static ArrayList recordType = new ArrayList<>(Arrays.asList(RecordType.values())); - - /** - * 用于存储模块信息,包含模块名称、模块步骤数量和模块bug数量,由模块名称作为key - */ - private static HashMap module = new HashMap(16); - - //TODO 记录相关 - /** - * 用于存储当前测试模块名称 - */ - private static String moduleName = ""; - - /** - * 用于存储当前测试类名称 - */ - private static String testClassName = ""; - - /** - * 用于存储当前测试方法名称 - */ - private static String methodName = ""; - - /** - * 用于控制是否启用自动记录 - */ - private static boolean isStepRecord = true; - - /** - * 用于标识是否已经开始进行记录 - */ - private static boolean startRecord = false; - - /** - * 返回{@link Log_Old}类对象 - * - * @return {@link Log_Old}类对象 - */ - public static Log_Old getLog() { - return log; - } - - /** - * 返回{@link ExcelRecord_Old}类对象 - * - * @return {@link ExcelRecord_Old}类对象 - */ - public static ExcelRecord_Old getRecord() { - return record; - } - - /** - * 用于返回{@link Screenshot}类对象 - * - * @return {@link Screenshot}类对象 - */ - public static Screenshot getScreenshot() { - return screenshot; - } - - /** - * 用于设置需要使用的工具类,通过传入枚举类{@link RecordType}的值类决定使用哪些记录工具 - * - * @param recordTypes {@link RecordType}指定的枚举值,可传入多个 - */ - public static void setRecordType(RecordType... recordTypes) { - // 清空recordType中的记录,重新进行存储,避免上一次的设置导致无需使用的工具类在进行记录 - recordType.clear(); - // 将相应使用的记录工具进行存储至recordType中,并对存在对象的类进行构造 - for (RecordType type : recordTypes) { - recordType.add(type); - } - } - - /** - * 设置模块信息,若bug数和步骤数中的一个未存储该模块信息时,则直接将两个数量初始化。 - * 根据传入的createFolder参数,控制是否创建文件,注意,该方法会只获取一次当前的文件夹路径, - * 请第一次将createFolder设置为true时一定要保证所使用的记录工具的文件保存路径处于 - * 根路径状态,否则文件夹创建的位置可能无法达到期望的效果 - * - * @param moduleName 模块名称 - * @param createFolder 是否创建新的文件夹 - * @throws RecordStateException 当已调用{@link #startRecord(String, String)}方法后再调用此方法是抛出 - */ - public static void setModule(String moduleName, boolean createFolder) { - // 当运行状态为true时,说明已经开始进行记录,则不能切换模块,否则抛出异常 - if (startRecord) { - throw new RecordStateException("当前已开始进行运行记录,无法切换模块"); - } - - // 判断bugNumber和stepNumber是否都有存储该模块,若其中一个未存储,则将两个map初始化 - if (!module.containsKey(moduleName)) { - module.put(moduleName, new ModuleInformation(moduleName)); - //判断是否需要冲洗创建新的文件夹 - if (createFolder) { - if (logSavePath.isEmpty()) { - logSavePath = log.getSavePath(); - } - - if (recordSavePath.isEmpty()) { - recordSavePath = record.getSavePath(); - } - - if (screenshotSavePath.isEmpty()) { - screenshotSavePath = screenshot.getSavePath(); - } - - log.setSavePath(logSavePath + moduleName + "/"); - record.setSavePath(logSavePath + moduleName + "/"); - screenshot.setSavePath(logSavePath + moduleName + "/RunScreenshot/"); - } - } - - // 设置当前的模块 - RecordTool.moduleName = moduleName; - } - - /** - * 用于返回存储在类中的所有模块的名称 - * @return 所有模块的名称 - */ - public static Set getModuleName() { - return module.keySet(); - } - - /** - * 返回当前模块的文本信息 - * - * @return 模块的文本信息 - */ - public static String getModuleInformation() { - return module.get(moduleName).getStringReport(0); - } - - /** - * 返回指定模块的文本信息 - * - * @param module 模块名称 - * @return 模块的文本信息 - */ - public static String getModuleInformation(String moduleName) { - return module.containsKey(moduleName) ? module.get(moduleName).getStringReport(0) : ""; - } - - /** - * 以Json格式返回当前模块的信息,详细字段见{@link ModuleInformation#getJsonInformation()} - * - * @return 模块的Json格式信息 - */ - public static String getModuleJsonInformation() { - return module.get(moduleName).getJsonInformation().toString(); - } - - /** - * 以Json格式返回指定模块的信息 - * - * @param module 模块名称 - * @return 模块的Json格式信息 - */ - public static String getModuleJsonInformation(String moduleName) { - return module.containsKey(moduleName) ? module.get(moduleName).getJsonInformation().toString() : ""; - } - - public static String getAllModuleInformation() { - String text = ""; - //读取module中所有的信息 - for (String key : module.keySet()) { - text += (getModuleInformation(key) + "\n"); - } - - return text; - } - - /** - * 用于指定是否进行自动记录操作步骤 - * - * @param isRecord 指定是否启用自动记录操作步骤 - */ - public static void setRecordStep(boolean isRecord) { - RecordTool.isStepRecord = isRecord; - } - - /** - * 用于返回是否启动自动记录操作步骤的状态 - * - * @return 是否开启自动记录操作步骤 - */ - public static boolean isRecordStep() { - return RecordTool.isStepRecord; - } - - /** - *

    - * 用于记录自动化测试中进行的操作步骤。根据{@link #setRecordType(RecordType...)}方法指定使用的工具进行记录,若未指定工具, - * 则默认使用所有的工具。在事件类中已写入该方法对步骤进行自动记录,亦可通过{@link #isRecord(boolean)}方法控制是否需要进行自动记录。 - *

    - *

    - * 注意:当未调用{@link #startRecord(String, String)}方法时,使用该方法不会抛出异常,以避免自动化测试不正常的结束 - *

    - * - * @param stepText 步骤内容 - */ - public static void recordStep(String stepText) { - // 当运行状态为false时,说明未开始进行记录,则不能进行记录,但不抛出异常,以避免自动化的结束 - if (!startRecord) { - return; - } - - // 判断是否需要进行步骤记录,若isRecord为false,则直接结束 - if (!isStepRecord) { - return; - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 记录前,步骤数+1 - module.get(moduleName).getTestClass().getMethod().addStep(); - // 循环,根据recordType中指定使用的记录工具进行记录 - recordType.forEach(e -> writeStep(e, stepText)); - } - - /** - *

    - * 用于记录自动化运行的结果,根据传入的判断结果(形参judgeResult),当其为true时, - * 则记录形参successText中的内容,反之,则记录形参errorText中的内容,并将其列为Bug,其模块中的Bug数加1。 - *

    - * - *

    - * 例如,我们在页面上当存在“取消”按钮时,则表示测试不通过,则可用以下代码表示: - * RecordTool.recordResult(!event.getJudgeEvent().judgeControl("取消").getBooleanValue(), - * "成功", "失败"); - *

    - * - *

    - * 记录工具根据{@link #setRecordType(RecordType...)}方法指定使用的工具进行记录,若未指定工具,则默认使用所有的工具。 - * 在事件类中已写入该方法对步骤进行自动记录,亦可通过{@link #isRecord(boolean)}方法控制是否需要进行自动记录。 - * 使用该方法时即使未使用截图工具,也会自动进行截图,并将截图附在记录的内容中。 当截图类配置有误时,则不进行截图,并将配置错误的信息, - * 记录在其他记录工具中。 - *

    - * - * @param judgeResult 判断结果 - * @param successText judgeResult为true时进行记录的文本 - * @param errorText judgeResult为false时进行记录的文本 - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - * @throws RecordStateException 当未调用{@link #startRecord(String, String)}方法是抛出的异常 - */ - public static void recordResult(boolean judgeResult, String successText, String errorText) { - // 当运行状态为false时,说明未开始进行记录,则不能进行记录,故抛出异常 - if (!startRecord) { - throw new RecordStateException("当前未开始进行运行记录,无法进行运行记录"); - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 记录截图文件原保存位置,以方便在当前路径下加上Result文件夹 - String screenshotPath = screenshot.getSavePath(); - // 将当前截图放到原路径下的Result文件夹下 - screenshot.setSavePath(screenshotPath + "Result/"); - // 根据传入的结果,判断使用哪一个记录语 - String resultText = judgeResult ? successText : errorText; - - // 根据传入的判断结果,为true时,则使用successText记录,并标记为非Bug,反之,则标记为Bug - File screenshotFile = null; - try { - screenshotFile = screenshot.creatImage(resultText); - } catch (WebDriverException | IOException e1) { - } - - // 由于lambda中不能写screenshotFile,故只能使用原始的forEach - for (RecordType type : recordType) { - writeResult(screenshotFile, type, !judgeResult, resultText); - } - - // 将截图存放位置返回到之前的存储路径下 - screenshot.setSavePath(screenshotPath); - - // 若结果为BUG则对当前测试方法对象中添加BUG数量 - if (!judgeResult) { - module.get(moduleName).getTestClass().getMethod().addBug(); - } - } - - /** - * 用于记录自动化运行的结果,当参数isBug为true时,将其列为Bug,模块中的Bug数加1,反之则不进行增加。 - *

    - * 记录工具根据{@link #setRecordType(RecordType...)}方法指定使用的工具进行记录,若未指定工具,则默认使用所有的工具。 - * 在事件类中已写入该方法对步骤进行自动记录,亦可通过{@link #isRecord(boolean)}方法控制是否需要进行自动记录。 - * 使用该方法时即使未使用截图工具,也会自动进行截图,并将截图附在记录的内容中。 当截图类配置有误时,则不进行截图,并将配置错误的信息, - * 记录在其他记录工具中。 - *

    - * - * @param isBug 是否为Bug - * @param text 结果文本 - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - * @throws RecordStateException 当未调用{@link #startRecord(String, String)}方法是抛出的异常 - */ - public static void recordResult(boolean isBug, String text) { - // 当运行状态为false时,说明未开始进行记录,则不能进行记录,故抛出异常 - if (!startRecord) { - throw new RecordStateException("当前未开始进行运行记录,无法进行运行记录"); - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 记录截图文件原保存位置,以方便在当前路径下加上Result文件夹 - String screenshotPath = screenshot.getSavePath(); - // 将当前截图放到原路径下的Result文件夹下 - screenshot.setSavePath(screenshotPath + "Result/"); - - // 根据传入的判断结果,为true时,则使用successText记录,并标记为非Bug,反之,则标记为Bug - File screenshotFile = null; - try { - screenshotFile = screenshot.creatImage(text); - } catch (WebDriverException | IOException e1) { - } - - // 由于lambda中不能写screenshotFile,故只能使用原始的forEach - for (RecordType type : recordType) { - writeResult(screenshotFile, type, isBug, text); - } - - // 将截图存放位置返回到之前的存储路径下 - screenshot.setSavePath(screenshotPath); - - // 若结果为BUG则对当前测试方法对象中添加BUG数量 - if (isBug) { - module.get(moduleName).getTestClass().getMethod().addBug(); - } - } - - /** - *

    - * 用于记录备注消息,记录工具根据{@link #setRecordType(RecordType...)}方法指定使用的工具进行记录, - * 若未指定工具,则默认使用所有的工具。在事件类中已写入该方法对步骤进行自动记录,亦可通过{@link #isRecord(boolean)}方法控制是否需要进行自动记录。 - *

    - * - * @param markText 备注文本 - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - * @throws RecordStateException 当未调用{@link #startRecord(String, String)}方法是抛出的异常 - */ - public static void recordMark(String markText) { - // 当运行状态为false时,说明未开始进行记录,则不能进行记录,故抛出异常 - if (!startRecord) { - return; - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 循环,根据recordType中指定使用的记录工具进行记录 - recordType.forEach(type -> writeMark(type, markText)); - } - - /** - *

    - * 用于记录异常消息,记录工具根据{@link #setRecordType(RecordType...)}方法指定使用的工具进行记录, - * 若未指定工具,则默认使用所有的工具。在事件类中已写入该方法对步骤进行自动记录,亦可通过{@link #isRecord(boolean)}方法控制是否需要进行自动记录。 - *

    - * @param exception 异常类 - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - */ - public static void recordException(Exception exception) { - // 当运行状态为false时,说明未开始进行记录,则不能进行记录,故抛出异常 - if (!startRecord) { - return; - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 记录截图文件原保存位置,以方便在当前路径下加上Result文件夹 - String screenshotPath = screenshot.getSavePath(); - // 将当前截图放到原路径下的Result文件夹下 - screenshot.setSavePath(screenshotPath + "Exception/"); - - // 根据传入的判断结果,为true时,则使用successText记录,并标记为非Bug,反之,则标记为Bug - File screenshotFile = null; - try { - // 将异常类名作为截图文件名 - screenshotFile = screenshot.creatImage(exception.getClass().getName()); - } catch (WebDriverException | IOException e1) { - } - - // 由于lambda中不能写screenshotFile,故只能使用原始的forEach - for (RecordType type : recordType) { - writeException(type, screenshotFile, exception); - } - - // 将截图存放位置返回到之前的存储路径下 - screenshot.setSavePath(screenshotPath); - } - - /** - * 用于控制开始使用记录工具进行运行记录,只有在使用该方法后以下方法才能生效: - * {@link #recordException(Exception)}、{@link #recordMark(String)}、 - * {@link #recordResult(boolean, String)}、{@link #recordResult(boolean, String, String)} - * - * @param className 测试类的名称 - * @param methodName 测试方法的名称 - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - * @throws RecordStateException 未调用结束记录的方法时再次调用了此方法后抛出的异常 - */ - public static void startRecord(String className, String methodName) { - // 当运行状态为true时,说明此次调用前未调用endWrite()方法,则抛出异常 - if (startRecord) { - throw new RecordStateException("当前运行状态为" + startRecord + ",需要调用结束记录的方法再调用该方法"); - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 记录类名与方法名 - testClassName = className; - RecordTool.methodName = methodName; - - //向内部类中添加信息 - module.get(moduleName).addTestClass(className); - module.get(moduleName).getTestClass().addMethod(methodName); - - // 设置运行记录状态为true - startRecord = true; - - // 由于lambda中不能写screenshotFile,故只能使用原始的forEach - for (RecordType type : recordType) { - writeStartRecord(type, className, methodName); - } - } - - /** - * 用于标识结束进行自动化测试运行记录,运行该方法后,所有的记录将停止 - * - * @throws RecordToolConfigException 记录工具配置错误时抛出的异常 - * @throws RecordStateException 未调用开始记录的方法时调用了此方法后抛出的异常 - */ - public static void endRecord() { - if (!startRecord) { - throw new RecordStateException("当前运行状态为" + startRecord + ",需要调用开始记录的方法再调用该方法"); - } - - // 判断模块内信息是否为,若为空,则加上一个“未命名模块” - if (module.isEmpty()) { - setModule("未命名模块", true); - } - - // 设置运行记录状态为false - startRecord = false; - - // 由于lambda中不能写screenshotFile,故只能使用原始的forEach - for (RecordType type : recordType) { - writeEndRecord(type); - } - } - - /** - * 用于根据模块名称生成指向模块的xmind版本的测试报告 - * @param projectedName 项目名称 - * @throws IOException 当文件不存在或错误时抛出的异常 - */ - public static void createXmindReport(String projectedName) throws IOException { - //读取模板文件,将文件的内容写入到jsonScript中 - BufferedReader bf = new BufferedReader(new FileReader(new File("Templet\\XMindTemplate\\content.json"))); - String jsonScript = ""; - String line = ""; - while ((line = bf.readLine()) != null) { - jsonScript += line; - } - bf.close(); - - //将模板中的json转换为JSONObject类,并添加标题与id - JSONObject json = JSON.parseObject(jsonScript); - json.getJSONObject("rootTopic").put("title", projectedName); - json.getJSONObject("rootTopic").put("id", UUID.randomUUID()); - - //循环,读取所有的模块信息 - int moduleIndex = 0; - for (String moduleName : module.keySet()) { - //读取模块信息的json - JSONObject moduleJson = JSON.parseObject(RecordTool.getModuleJsonInformation(moduleName)); - //编写模块信息 - addChildren(json.getJSONObject("rootTopic"), moduleName); - - //读取模块下testclass中所有的内容 - JSONArray testClassList = moduleJson.getJSONArray("testClass"); - //循环,读取所有的测试类信息 - for (int testClassIndex = 0; testClassIndex < testClassList.size(); testClassIndex++) { - //读取每一个测试类json - JSONObject testClassJson = JSON.parseObject(testClassList.get(testClassIndex).toString()); - //编写测试类信息 - addChildren(json.getJSONObject("rootTopic"). - getJSONObject("children").getJSONArray("attached"). - getJSONObject(moduleIndex), testClassJson.getString("name")); - - //读取模块下method中所有的内容 - JSONArray methodList = testClassJson.getJSONArray("method"); - //循环,读取测试类下所有的测试方法 - for (int methodIndex = 0; methodIndex < methodList.size(); methodIndex++) { - //读取每一个测试方法的json - JSONObject methodJson = JSON.parseObject(methodList.get(methodIndex).toString()); - //写入测试方法信息 - String methodInformation = "方法名:"; - methodInformation += (methodJson.getString("name") + "\n"); - methodInformation += ("步骤数量:" + methodJson.getString("step") + "\n"); - methodInformation += ("Bug数量:" + methodJson.getString("bug") + "\n"); - //编写测试方法信息 - addChildren(json.getJSONObject("rootTopic"). - getJSONObject("children").getJSONArray("attached"). - getJSONObject(moduleIndex). - getJSONObject("children").getJSONArray("attached"). - getJSONObject(testClassIndex), methodInformation); - } - - //添加出现BUG的方法文本,若无出现BUG的方法,则不添加该分支 - if (!testClassJson.getJSONArray("bugMethod").isEmpty()) { - addChildren(json.getJSONObject("rootTopic"). - getJSONObject("children").getJSONArray("attached"). - getJSONObject(moduleIndex). - getJSONObject("children").getJSONArray("attached"). - getJSONObject(testClassIndex), "出现bug的方法有:" + testClassJson.getString("bugMethod")); - } - } - moduleIndex++; - } - - //在json代码前后加上中括号,以适应xmind的读取方式 - jsonScript = "["; - jsonScript += json.toString(); - jsonScript += "]"; - - //添加文件夹 - new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/").mkdirs(); - //存储测试报告相关的json文件生成至相应的位置 - BufferedWriter bw = new BufferedWriter(new FileWriter(new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/" + "content.json"))); - bw.write(jsonScript); - bw.close(); - - //将模板中的文件复制到默认的位置,由于使用FileUtil指向的相对路径并非当前的工程路径,故需要先将绝对路径转为相对路径后再添加 - //由于生成的绝对路径数据末尾不带“/”,故需要在文件名前补上 - FileUtil.copy(new File(XMIND_TEMJPLET_FILE_PATH).getAbsoluteFile() + "/content.xml", new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/").getAbsolutePath(), true); - FileUtil.copy(new File(XMIND_TEMJPLET_FILE_PATH).getAbsoluteFile() + "/manifest.json", new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/").getAbsolutePath(), true); - FileUtil.copy(new File(XMIND_TEMJPLET_FILE_PATH).getAbsoluteFile() + "/metadata.json", new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/").getAbsolutePath(), true); - //压缩文件,将文件打包成xmind格式的文件 - compressReportFile(new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/")); - - //删除复制到目录中的文件,只保留生成的xmind文件 - Arrays.asList(new File(DEFAULT_FILE_PATH + projectedName + "自动化测试报告/").listFiles()).stream(). - filter(file -> file.getName().indexOf(".xmind") == -1).forEach(File :: delete); - - } - - /** - * 压缩文件,并打包成xmind的格式 - * @param reportFolder xmind文件存放文件夹 - * @throws IOException 文件错误时抛出的异常 - */ - private static void compressReportFile(File reportFolder) throws IOException { - // 获取测试报告文件夹中所有的文件 - File[] fileList = reportFolder.listFiles(); - // 创建压缩文件流对象 - ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream( - new FileOutputStream(new File(reportFolder, reportFolder.getName() + ".xmind")))); - // 定义缓存变量 - byte[] bufs = new byte[1024 * 10]; - // 循环,将文件夹中的文件全部写入到压缩文件中 - for (int i = 0; i < fileList.length; i++) { - // 创建ZIP实体,并添加进压缩包 - zos.putNextEntry(new ZipEntry(fileList[i].getName())); - FileInputStream fis = new FileInputStream(fileList[i]); - BufferedInputStream bis = new BufferedInputStream(fis, 1024 * 10); - int read = 0; - while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) { - zos.write(bufs, 0, read); - } - - bis.close(); - } - zos.close(); - } - - /** - * 用于生成xmind测试报告中添加下级标题的方法 - * @param parentJson json父节点 - * @param title 写入到文件中的内容 - */ - private static void addChildren(JSONObject parentJson, String title) { - JSONObject childrenJson = new JSONObject(); - - childrenJson.put("id", UUID.randomUUID()); - childrenJson.put("title", title); - - if (!parentJson.containsKey("children")) { - parentJson.put("children", new JSONObject()); - } - - if (!parentJson.getJSONObject("children").containsKey("attached")) { - parentJson.getJSONObject("children").put("attached", new ArrayList<>()); - } - - parentJson.getJSONObject("children").getJSONArray("attached").add(childrenJson); - } - - /** - * 用于对测试方法运行结束时的记录 - * - * @param type 记录工具类型 - */ - private static void writeEndRecord(RecordType type) { - // 根据RecordType选择记录工具,若截图文件对象为null,则不记录截图文件 - switch (type) { - case LOG: - try { - log.endWrite(module.get(moduleName).getTestClass().getMethod().getBug()); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入结果"); - } - break; - case RECORD: - try { - record.endRecord(); - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入结果"); - } - break; - case SCREENSHOT: - // 此处无需截图 - break; - case SYSTEM: - System.out.println(testClassName + "类的" + methodName + "方法运行结束,共发现BUG" - + module.get(moduleName).getTestClass().getMethod().getBug() + "个"); - break; - default: - throw new IllegalArgumentException("未定义的枚举值: " + type); - } - } - - /** - * 用于对测试方法开始运行时进行记录 - * - * @param type 记录工具类型 - * @param className 运行类名 - * @param methodName 运行方法名 - */ - private static void writeStartRecord(RecordType type, String className, String methodName) { - // 根据RecordType选择记录工具,若截图文件对象为null,则不记录截图文件 - switch (type) { - case LOG: - try { - log.startWrite(className, methodName); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入结果"); - } - break; - case RECORD: - try { - record.startRecord(className, methodName); - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入结果"); - } - break; - case SCREENSHOT: - // 此处无需截图 - break; - case SYSTEM: - System.out.println("正在运行" + className + "类的" + methodName + "()方法"); - break; - default: - throw new IllegalArgumentException("未定义的枚举值: " + type); - } - } - - /** - * 用于对异常进行记录 - * - * @param type 记录工具类型 - * @param screenshotFile 截图文件类对象 - * @param exception 异常类对象 - */ - private static void writeException(RecordType type, File screenshotFile, Exception exception) { - // 根据RecordType选择记录工具,若截图文件对象为null,则不记录截图文件 - switch (type) { - case LOG: - try { - log.write("出现异常,其异常信息如下:\n" + "异常名称:" + exception.getClass().getName() + "\n异常信息:" - + exception.getMessage() + "\n" - + (screenshotFile != null ? ("详见截图:" + screenshotFile.getAbsolutePath()) - : "Screenshot类配置有误,无法进行截图")); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入结果"); - } - case RECORD: - try { - record.setException(exception); - if (screenshotFile != null) { - record.errorScreenshot(screenshotFile); - } else { - record.mark("Screenshot类配置有误,无法进行截图"); - } - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入结果"); - } - break; - case SCREENSHOT: - // 由于在recordResult()方法中采用直接截图的方式,故此处可不做操作 - break; - case SYSTEM: - System.out.println( - "出现异常,其异常信息如下:\n" + "异常名称:" + exception.getClass().getName() + "\n异常信息:" + exception.getMessage() - + "\n" + (screenshotFile != null ? ("详见截图:" + screenshotFile.getAbsolutePath()) - : "Screenshot类配置有误,无法进行截图")); - break; - default: - throw new IllegalArgumentException("未定义的枚举值: " + type); - } - } - - /** - * 用于选择工具将备注文本写入到相应的工具中 - * - * @param type 记录工具类型 - * @param markText 需要记录的备注消息 - */ - private static void writeMark(RecordType type, String markText) { - // 根据RecordType选择记录工具 - switch (type) { - case LOG: - try { - log.write("备注:" + markText); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入步骤"); - } - break; - case RECORD: - try { - record.mark(markText); - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入步骤"); - } - break; - case SCREENSHOT: - try { - String path = screenshot.getSavePath(); - screenshot.setSavePath(path + "mark/"); - screenshot.creatImage(markText); - screenshot.setSavePath(path); - } catch (WebDriverException | IOException e) { - throw new RecordToolConfigException("Scerrnshot类配置错误,无法进行截图"); - } - break; - case SYSTEM: - System.out.println("备注:" + markText); - break; - default: - throw new IllegalArgumentException("未定义的值: " + type); - } - } - - /** - * 用于根据使用的记录工具类型,对测试结果进行记录 - * - * @param screenshotFile 截图文件类对象 - * @param type 记录工具类型 - * @param isBug 是否为Bug - * @param resultText 需要记录的内容 - */ - private static void writeResult(File screenshotFile, RecordType type, boolean isBug, String resultText) { - // 根据RecordType选择记录工具,若截图文件对象为null,则不记录截图文件 - switch (type) { - case LOG: - try { - log.write("结果:" + resultText + "\n" - + (screenshotFile != null ? ("详见截图:" + screenshotFile.getAbsolutePath()) - : "Screenshot类配置有误,无法进行截图")); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入结果"); - } - break; - case RECORD: - try { - record.result(resultText, isBug); - if (screenshotFile != null) { - record.runScreenshot(screenshotFile); - } else { - record.mark("Screenshot类配置有误,无法进行截图"); - } - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入结果"); - } - break; - case SCREENSHOT: - // 由于在recordResult()方法中采用直接截图的方式,故此处可不做操作 - break; - case SYSTEM: - System.out.println( - "结果:" + resultText + "\n" + (screenshotFile != null ? ("详见截图:" + screenshotFile.getAbsolutePath()) - : "Screenshot类配置有误,无法进行截图")); - break; - default: - throw new IllegalArgumentException("未定义的枚举值: " + type); - } - } - - /** - * 用于根据指定的记录工具类型,对步骤进行记录 - * - * @param type 记录工具的 - * @param stepText 当前的步骤的内容 - */ - private static void writeStep(RecordType type, String stepText) { - // 根据RecordType选择记录工具 - switch (type) { - case LOG: - try { - log.write("步骤:" + module.get(moduleName).getTestClass().getMethod().getStep() + "." + stepText); - } catch (IOException e) { - throw new RecordToolConfigException("Log类配置错误,无法写入步骤"); - } - break; - case RECORD: - try { - record.step(stepText); - } catch (Exception e) { - throw new RecordToolConfigException("Record类配置错误,无法写入步骤"); - } - break; - case SCREENSHOT: - try { - String path = screenshot.getSavePath(); - screenshot.setSavePath(path + "step/"); - screenshot.creatImage(module.get(moduleName).getTestClass().getMethod().getStep() + ""); - screenshot.setSavePath(path); - } catch (WebDriverException | IOException e) { - throw new RecordToolConfigException("Scerrnshot类配置错误,无法进行截图"); - } - break; - case SYSTEM: - System.out.println("步骤:" + module.get(moduleName).getTestClass().getMethod().getStep() + "." + stepText); - break; - default: - throw new IllegalArgumentException("未定义的值: " + type); - } - } - - /** - *

    - * 文件名:RecordTool.java - *

    - *

    - * 用途:用于存储、输出模块信息 - *

    - *

    - * 编码时间:2019年9月21日下午4:28:30 - *

    - *

    - * 修改时间:2019年10月6日下午5:19:30 - *

    - * - * @author 彭宇琦 - * @version Ver1.1 - * @since JDK 12 - * - */ - private static class ModuleInformation implements AutoTestReport { - /** - * 用于存储模块包含的用例类信息 - */ - private HashMap moduleInformation = new HashMap( - 16); - - /** - * 用于记录模块的名称 - */ - private String moduleName = ""; - - /** - * 初始化模块信息 - */ - public ModuleInformation(String moduleName) { - this.moduleName = moduleName; - } - - /** - * 用于记录并初始化测试用例类的信息,若信息已存在,则不进行存储 - * - * @param testClassName 测试用例类名称 - */ - public void addTestClass(String testClassName) { - // 判断当前测试类名称是否存在,存在则不进行初始化 - if (!moduleInformation.containsKey(testClassName)) { - moduleInformation.put(testClassName, new TestClassInformation(testClassName)); - } - } - - /** - * 用于返回当前指向的测试类对象 - * - * @return 当前指向的测试类对象 - */ - public TestClassInformation getTestClass() { - return moduleInformation.get(testClassName); - } - - /** - * 以json格式,输出测试模块信息,json包含字段及类型如下:
    - * name:模块名称,为String类型
    - * testClass:模块中包含的所有测试类的信息,为List类型(该字段调用{@link TestClassInformation#getJsonInformation()})
    - * - * @return 测试类信息,json格式 - */ - @Override - public JSONObject getJsonInformation() { - JSONObject json = new JSONObject(); - json.put("name", moduleName); - // 添加模块下所有的方法信息 - ArrayList testClassList = new ArrayList<>(); - moduleInformation.forEach((key, value) -> { - testClassList.add(value.getJsonInformation()); - }); - json.put("testClass", testClassList); - - return json; - } - - @Override - public String getStringReport(int tabCount) { - // 记录测试模块名称 - String text = "\t".repeat(tabCount) + "测试模块名:" + moduleName + "\n"; - - // 记录每个测试方法中的信息 - text += "\t".repeat(tabCount) + "以下是测试模块中所有的测试类的信息:\n"; - for (String key : moduleInformation.keySet()) { - text += moduleInformation.get(key).getStringReport(tabCount + 1); - } - text += "\n"; - - return text; - } - } - - /** - *

    - * 文件名:RecordTool.java - *

    - *

    - * 用途:用于存储、输出测试类的信息 - *

    - *

    - * 编码时间:2019年10月6日下午5:10:51 - *

    - *

    - * 修改时间:2019年10月6日下午5:10:51 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ - private static class TestClassInformation implements AutoTestReport { - /** - * 用于存储用例类包含的用例信息 - */ - private HashMap testClassInforemation = new HashMap( - 16); - - /** - * 用于记录用例类的名称 - */ - private String testClassName = ""; - - /** - * 用于初始化测试类的名称 - * - * @param testClassName 测试类的名称 - */ - public TestClassInformation(String testClassName) { - this.testClassName = testClassName; - } - - /** - * 用于记录并初始化测试用例类的信息,若信息已存在,则不进行存储 - * - * @param testClassName 测试用例类名称 - */ - public void addMethod(String methodName) { - // 判断当前测试类名称是否存在,存在则不进行初始化 - if (!testClassInforemation.containsKey(methodName)) { - testClassInforemation.put(methodName, new MethodInformation(methodName)); - } - } - - /** - * 用于返回当前指向的测试方法对象 - * - * @return 当前指向的测试方法对象 - */ - public MethodInformation getMethod() { - return testClassInforemation.get(methodName); - } - - /** - * 以json格式,输出测试类信息,json包含字段及类型如下:
    - * name:测试类名称,为String类型
    - * method:测试类中包含的所有方法的信息,为List类型(该字段调用{@link MethodInformation#getJsonInformation()})
    - * bugMethod:测试类中出现BUG的方法信息 - * - * @return 测试类信息,json格式 - */ - @Override - public JSONObject getJsonInformation() { - JSONObject json = new JSONObject(); - json.put("name", testClassName); - // 添加测试类下所有的方法信息 - ArrayList methodList = new ArrayList<>(); - testClassInforemation.forEach((key, value) -> { - methodList.add(value.getJsonInformation()); - }); - json.put("method", methodList); - - // 添加出现Bug的测试方法的方法名 - ArrayList bugMethodList = new ArrayList<>(); - testClassInforemation.forEach((key, value) -> { - // 若该方法为出现BUG的测试方法,则进行存储其方法名(key则为方法名) - if (value.isBugMethod()) { - bugMethodList.add(key); - } - }); - json.put("bugMethod", bugMethodList); - - return json; - } - - @Override - public String getStringReport(int tabCount) { - // 记录测试类名称 - String text = "\t".repeat(tabCount) + "测试类名:" + testClassName + "\n"; - // 记录测试类中出现BUG的方法名 - text += "\t".repeat(tabCount) + "出现Bug的方法有:"; - for (String key : testClassInforemation.keySet()) { - // 若该方法为出现BUG的测试方法,则进行存储其方法名(key则为方法名) - if (testClassInforemation.get(key).isBugMethod()) { - text += key; - } - } - text += "\n"; - - // 记录每个测试方法中的信息 - text += "\t".repeat(tabCount) + "以下是测试类中所有的测试方法的信息:\n"; - for (String key : testClassInforemation.keySet()) { - text += testClassInforemation.get(key).getStringReport(tabCount + 1); - } - text += "\n"; - - return text; - } - } - - /** - *

    - * 文件名:RecordTool.java - *

    - *

    - * 用途:用于存储、输出测试方法的信息 - *

    - *

    - * 编码时间:2019年10月6日下午4:47:33 - *

    - *

    - * 修改时间:2019年10月6日下午4:47:33 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - * - */ - private static class MethodInformation implements AutoTestReport { - /** - * 用于记录步骤数 - */ - private int step = 0; - - /** - * 用于记录Bug数 - */ - private int bug = 0; - - /** - * 用于标记该没方法是否出现Bug - */ - private boolean bugMethod = false; - - /** - * 用于记录方法的名称 - */ - private String methodName = ""; - - /** - * 初始化用例信息 - */ - public MethodInformation(String methodName) { - this.methodName = methodName; - } - - /** - * 用于增加步骤的数量 - */ - public void addStep() { - step++; - } - - /** - * 用于增加Bug的数量,并设置当前方法为出现Bug方法 - */ - public void addBug() { - bug++; - bugMethod = true; - } - - /** - * 用于返回当前方法的步骤数量 - * - * @return 步骤数量 - */ - public int getStep() { - return step; - } - - /** - * 用于返回当前方法的Bug数量 - * - * @return Bug数量 - */ - public int getBug() { - return bug; - } - - /** - * 返回方法是否为出现Bug的方法 - * - * @return 是否为出现Bug的方法 - */ - public boolean isBugMethod() { - return bugMethod; - } - - /** - * 以json格式,输出方法信息,json包含字段及类型如下:
    - * name:方法名称,为String类型
    - * bug:方法的Bug数量,为int类型
    - * step:方法的步骤数量,为int类型
    - * isBugMethod:标记方法是否为出现Bug的方法,为boolean类型 - * - * @return 方法信息,json格式 - */ - @Override - public JSONObject getJsonInformation() { - JSONObject json = new JSONObject(); - json.put("name", methodName); - json.put("bug", bug); - json.put("step", step); - json.put("isBugMethod", bugMethod); - return json; - } - - @Override - public String getStringReport(int tabCount) { - // 记录方法名称 - String text = "\t".repeat(tabCount) + "测试方法名:" + methodName + "\n"; - // 记录步骤数量 - text += "\t".repeat(tabCount) + "步骤数量:" + step + "\n"; - // 记录Bug数量 - text += "\t".repeat(tabCount) + "Bug数量:" + bug + "\n"; - - // 返回文本 - return text; - } - } - - /** - *

    - * 文件名:RecordTool.java - *

    - *

    - * 用途:用于定义每个与自动化测试报告记录相关的接口 - *

    - *

    - * 编码时间:2019年10月6日下午3:07:11 - *

    - *

    - * 修改时间:2019年10月6日下午3:07:11 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 12 - */ - private interface AutoTestReport { - /** - * 以json格式输出自动化测试运行的结果 - * - * @return json格式,自动化测试运行的结果 - */ - JSONObject getJsonInformation(); - - /** - * 以文本的形式输出自动化测试的结果 - * - * @param tabCount 文本前tab的个数,调整格式使用 - * @return 文本格式,自动化测试的结果 - */ - String getStringReport(int tabCount); - } -} \ No newline at end of file diff --git a/src/main/java/pres/auxiliary/work/selenium/tool/RecordToolConfigException.java b/src/main/java/pres/auxiliary/work/selenium/tool/RecordToolConfigException.java deleted file mode 100644 index 2b1987b..0000000 --- a/src/main/java/pres/auxiliary/work/selenium/tool/RecordToolConfigException.java +++ /dev/null @@ -1,38 +0,0 @@ -package pres.auxiliary.work.selenium.tool; - -/** - *

    文件名:RecordToolConfigException.java

    - *

    用途:使用RecordTool类时,其类中使用的工具未配置正确时抛出该异常

    - *

    编码时间:2019年9月22日上午11:48:16

    - *

    修改时间:2019年9月22日上午11:48:16

    - * @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); - } - -} diff --git a/src/main/java/pres/auxiliary/work/selenium/tool/RunLog.java b/src/main/java/pres/auxiliary/work/selenium/tool/RunLog.java deleted file mode 100644 index ae6b2fb..0000000 --- a/src/main/java/pres/auxiliary/work/selenium/tool/RunLog.java +++ /dev/null @@ -1,32 +0,0 @@ -package pres.auxiliary.work.selenium.tool; - -import java.io.File; - -/** - *

    文件名:RunLog.java

    - *

    用途: - * 以纯文本的形式记录自动化运行过程 - *

    - *

    编码时间:2020年9月3日上午8:02:37

    - *

    修改时间:2020年9月3日上午8:02:37

    - * @author 彭宇琦 - * @version Ver1.0 - * - */ -public class RunLog { - /** - * 指向日志文件类对象 - */ - private File logFile = null; - - public RunLog() { - } - - /** - * 构造对象,并指定日志存放位置 - * @param logFile 日志文件类对象 - */ - public RunLog(File logFile) { - this.logFile = logFile; - } -} diff --git a/src/test/java/pres/auxiliary/tool/date/TimeTest.java b/src/test/java/pres/auxiliary/tool/date/TimeTest.java index c06d5c1..ca37e42 100644 --- a/src/test/java/pres/auxiliary/tool/date/TimeTest.java +++ b/src/test/java/pres/auxiliary/tool/date/TimeTest.java @@ -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(); diff --git a/src/test/java/pres/auxiliary/tool/randomstring/PresetStringTest.java b/src/test/java/pres/auxiliary/tool/randomstring/PresetStringTest.java index d834acd..e5ae21b 100644 --- a/src/test/java/pres/auxiliary/tool/randomstring/PresetStringTest.java +++ b/src/test/java/pres/auxiliary/tool/randomstring/PresetStringTest.java @@ -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() { diff --git a/src/test/java/pres/auxiliary/tool/randomstring/RandomWordTest.java b/src/test/java/pres/auxiliary/tool/randomstring/RandomWordTest.java index b435078..23f897a 100644 --- a/src/test/java/pres/auxiliary/tool/randomstring/RandomWordTest.java +++ b/src/test/java/pres/auxiliary/tool/randomstring/RandomWordTest.java @@ -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; + /** *

    文件名:RandomWordTest.java

    *

    用途: diff --git a/src/test/java/pres/auxiliary/work/selenium/datadriven/TestNGDataDriverTest.java b/src/test/java/pres/auxiliary/work/selenium/datadriven/TestNGDataDriverTest.java index 7c6d85c..927424e 100644 --- a/src/test/java/pres/auxiliary/work/selenium/datadriven/TestNGDataDriverTest.java +++ b/src/test/java/pres/auxiliary/work/selenium/datadriven/TestNGDataDriverTest.java @@ -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 { diff --git a/src/test/java/test/javase/RandomPhone.java b/src/test/java/test/javase/RandomPhone.java index 7b93c4f..56ae51f 100644 --- a/src/test/java/test/javase/RandomPhone.java +++ b/src/test/java/test/javase/RandomPhone.java @@ -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) { diff --git a/src/test/java/test/javase/SweepPlan.java b/src/test/java/test/javase/SweepPlan.java index 48b1e84..2ce2a6e 100644 --- a/src/test/java/test/javase/SweepPlan.java +++ b/src/test/java/test/javase/SweepPlan.java @@ -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 diff --git a/src/test/java/test/javase/TestArrayList.java b/src/test/java/test/javase/TestArrayList.java index c5dd81c..7fc0c94 100644 --- a/src/test/java/test/javase/TestArrayList.java +++ b/src/test/java/test/javase/TestArrayList.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 al = new ArrayList(); - 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 al = new ArrayList(); + 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())); + } + +} diff --git a/src/test/java/test/javase/TestCase2.java b/src/test/java/test/javase/TestCase2.java index dbbb8ea..8106f02 100644 --- a/src/test/java/test/javase/TestCase2.java +++ b/src/test/java/test/javase/TestCase2.java @@ -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 { diff --git a/src/test/java/test/javase/TestPresetStr.java b/src/test/java/test/javase/TestPresetStr.java index 4d31d6f..848ebff 100644 --- a/src/test/java/test/javase/TestPresetStr.java +++ b/src/test/java/test/javase/TestPresetStr.java @@ -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) { diff --git a/src/test/java/test/javase/TestRandomString.java b/src/test/java/test/javase/TestRandomString.java index adf4223..5925bca 100644 --- a/src/test/java/test/javase/TestRandomString.java +++ b/src/test/java/test/javase/TestRandomString.java @@ -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) { From 4599cdf9587c07d17779f5dd009b7c32cbaf14cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Fri, 27 Nov 2020 15:00:10 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=85=83=E7=B4=A0=E6=97=B6=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=9C=AA=E5=88=87=E6=8D=A2=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pres/auxiliary/work/selenium/element/Element.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/pres/auxiliary/work/selenium/element/Element.java b/src/main/java/pres/auxiliary/work/selenium/element/Element.java index 0401dcc..7ad1196 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/Element.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/Element.java @@ -86,6 +86,8 @@ public class Element { // }catch (TimeoutException e) { // } abstractBy.elementList = abstractBy.recognitionElement(elementData); + //切换当前读取的元素信息 + abstractBy.elementData = elementData; } @Override From 65b4411fa5a330e5597dbc74771e948351361b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Sat, 28 Nov 2020 20:48:51 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=B1=BB=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../selenium/event/extend/DataTableEvent.java | 107 +++++++++---- .../event/extend/DataTableEventTest.java | 146 ++++++++++++++++++ 2 files changed, 224 insertions(+), 29 deletions(-) create mode 100644 src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java index c5edc5c..4b8dae0 100644 --- a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java @@ -1,9 +1,10 @@ package pres.auxiliary.work.selenium.event.extend; import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Random; import java.util.function.BooleanSupplier; -import java.util.stream.IntStream; import org.openqa.selenium.Keys; @@ -44,7 +45,8 @@ public class DataTableEvent extends AbstractEvent { /** * 用于存储当前的列表元素 */ - protected ArrayList tableList = new ArrayList<>(); +// protected ArrayList tableList = new ArrayList<>(); + protected LinkedHashMap> tableMap = new LinkedHashMap<>(16); /** * 用于存储当前列表的长度 @@ -66,6 +68,7 @@ public class DataTableEvent extends AbstractEvent { clickEvent = new ClickEvent(brower); textEvent = new TextEvent(brower); + assertEvent = new AssertEvent(brower); } /** @@ -78,19 +81,28 @@ public class DataTableEvent extends AbstractEvent { } /** - * 用于添加一列元素,调用该方法时将对存储的 + * 用于添加一列元素,若启用严格校验(即通过{@link #setExamine(boolean)}方法设置为true), + * 则调用该方法时将对存储的数据个数进行校验,若传入的列元素个数与当前存储的列表元素个数 + * 不一致时,则抛出{@link InvalidDataListException}异常 + * + *

    + * 注意:传入的{@link DataListBy}类对象中元素的名称请勿与其他元素名称一致,否则会 + * 覆盖原有的元素列 + *

    + * * @param dataListBy 元素列查找对象 + * @throws InvalidDataListException 启用严格校验且元素个数与存储列表元素个数不一致时抛出的异常 */ public void add(DataListBy dataListBy) { //判断当前是否存储元素,若未存储元素,则不进行元素个数判断 - if (!tableList.isEmpty()) { + if (!tableMap.isEmpty()) { //判断传入的列的元素个数是否与当前存储的元素个数一致,若不一致,则进行个数判定校验 int nowSize = dataListBy.size(); - if (nowSize != size()) { + if (nowSize != listSize()) { //若当前需要严格校验列表元素个数,则抛出异常 if (isExamine) { throw new InvalidDataListException("当前传入的元素列个数与存储的元素列个数不一致!" - + "(当前元素列个数:" + size() + ",传入的元素列元素个数:" + nowSize + ")"); + + "(当前元素列个数:" + listSize() + ",传入的元素列元素个数:" + nowSize + ")"); } else { //若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 listSize = listSize < nowSize ? listSize : nowSize; @@ -101,7 +113,7 @@ public class DataTableEvent extends AbstractEvent { listSize = dataListBy.size(); } - tableList.add(dataListBy); + tableMap.put(dataListBy.getElement(1).getElementData().getName(), dataListBy.getAllElement()); } /** @@ -110,31 +122,43 @@ public class DataTableEvent extends AbstractEvent { * * @return 元素列的元素个数 */ - public int size() { + public int listSize() { return listSize; } + + public int listSize(String name) { + return tableMap.get(name).size(); + } + + /** + * 用于返回元素表中的列数 + * @return + */ + public int rowSize() { + return tableMap.size(); + } /** * 用于点击一次上一页按钮,并返回点击成功结果 - * @param upPageButton 上一页按钮元素 + * @param pageTurningButton 翻页按钮元素 * @return 点击结果 */ - public boolean upPage(Element upPageButton) { + public boolean pageTurning(Element pageTurningButton) { boolean result = operateSuchAssertData(() -> { //判断按钮是否可以点击 - if (!upPageButton.getWebElement().isEnabled()) { + if (!pageTurningButton.getWebElement().isEnabled()) { return false; } try { - clickEvent.click(upPageButton); + clickEvent.click(pageTurningButton); return true; } catch (Exception e) { return false; } }); - logText = "点击“" + upPageButton.getElementData().getName() + "”元素,返回列表上一页,其翻页" + logText = "点击“" + pageTurningButton.getElementData().getName() + "”元素,返回列表上一页,其翻页" + (result ? "" : "不") + "成功"; resultText = String.valueOf(result); @@ -143,23 +167,23 @@ public class DataTableEvent extends AbstractEvent { /** * 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数) - * @param upPageButton 上一页按钮元素 + * @param pageTurningButton 上一页按钮元素 * @param count 点击次数 * @return 实际点击次数 */ - public int upPage(Element upPageButton, int count) { + public int pageTurning(Element pageTurningButton, int count) { int nowCount = 0; //根据设置的点击次数循环点击上一页 while (nowCount < count) { //若点击成功,则nowCount自增,若点击失败,则退出循环 - if (upPage(upPageButton)) { + if (pageTurning(pageTurningButton)) { nowCount++; } else { break; } } - logText = "连续点击“" + upPageButton.getElementData().getName() + "”元素,使列表返回至上" + logText = "连续点击“" + pageTurningButton.getElementData().getName() + "”元素,使列表返回至上" + count + "页,其实际翻页数为:" + nowCount; resultText = String.valueOf(nowCount); @@ -169,22 +193,22 @@ public class DataTableEvent extends AbstractEvent { /** * 用于持续点击上一页按钮,直到按钮不可点击为止,并返回实际点击次数(实际点击次数) - * @param upPageButton 上一页按钮元素 + * @param pageTurningButton 上一页按钮元素 * @return 实际点击次数 */ - public int continueUpPage(Element upPageButton) { + public int continuePageTurning(Element pageTurningButton) { int nowCount = 0; //根据设置的点击次数循环点击上一页 while (true) { //若点击成功,则nowCount自增,若点击失败,则退出循环 - if (upPage(upPageButton)) { + if (pageTurning(pageTurningButton)) { nowCount++; } else { break; } } - logText = "持续点击“" + upPageButton.getElementData().getName() + "”元素,使列表返回至首页" + logText = "持续点击“" + pageTurningButton.getElementData().getName() + "”元素,使列表返回至首页" + ",其实际翻页数为:" + nowCount; resultText = String.valueOf(nowCount); @@ -250,7 +274,7 @@ public class DataTableEvent extends AbstractEvent { *

    *

    * 注意:下标将按照元素列长度进行计算,若下标的绝对值大于元素列长度,且下标为正数,则 - * 获取最后一行元素;反之,则获取第一行元素。元素列个数可参考{@link #size()}方法 + * 获取最后一行元素;反之,则获取第一行元素。元素列个数可参考{@link #listSize()}方法 *

    * * @param rowIndex 需要获取的行下标 @@ -259,8 +283,8 @@ public class DataTableEvent extends AbstractEvent { public ArrayList getRowElement(int rowIndex) { //根据下标,获取元素,并进行存储 ArrayList elementList = new ArrayList<>(); - IntStream.range(0, tableList.size()).forEach(index -> { - elementList.add(tableList.get(index).getElement(rowIndex)); + tableMap.forEach((key, value) -> { + elementList.add(value.get(toElementIndex(listSize(key), rowIndex))); }); return elementList; @@ -335,7 +359,7 @@ public class DataTableEvent extends AbstractEvent { private boolean operateSuchAssertData(BooleanSupplier action) { //若元素列表非空,则获取第一行元素,用于进行断言 ArrayList oldElementList = new ArrayList<>(); - if (!tableList.isEmpty()) { + if (!tableMap.isEmpty()) { //获取第一行元素 oldElementList = getRowElement(1); } @@ -344,18 +368,43 @@ public class DataTableEvent extends AbstractEvent { if (action.getAsBoolean()) { //获取操作后的第一行元素 ArrayList newElementList = new ArrayList<>(); - if (!tableList.isEmpty()) { + if (!tableMap.isEmpty()) { //获取第一行元素 newElementList = getRowElement(1); + //断言元素,并返回结果 + return assertDataChange(oldElementList, newElementList); + } else { + return true; } - - //断言元素,并返回结果 - return assertDataChange(oldElementList, newElementList); } else { return false; } } + public enum DataTableKeywordType { + /** + * 上一页按钮 + */ + UP_PAGE_BUTTON, + /** + * 下一页按钮 + */ + DOWN_PAGE_BUTTON, + /** + * 首页按钮 + */ + FIRST_PAGE_BUTTON, + /** + * 尾页按钮 + */ + LAST_PAGE_BUTTON, + /** + * 跳页按钮 + */ + JUMP_PAGE_BUTTON, + ; + } + /** *

    文件名:DataTableEvent.java

    *

    用途: diff --git a/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java new file mode 100644 index 0000000..0a805e4 --- /dev/null +++ b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java @@ -0,0 +1,146 @@ +package pres.auxiliary.work.selenium.event.extend; + +import java.io.File; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import pres.auxiliary.work.selenium.brower.ChromeBrower; +import pres.auxiliary.work.selenium.brower.ChromeBrower.ChromeOptionType; +import pres.auxiliary.work.selenium.element.CommonBy; +import pres.auxiliary.work.selenium.element.DataListBy; +import pres.auxiliary.work.selenium.element.Element; +import pres.auxiliary.work.selenium.event.TextEvent; +import pres.auxiliary.work.selenium.location.ByType; +import pres.auxiliary.work.selenium.location.NoFileLocation; + +/** + *

    文件名:DataTableEventTest.java

    + *

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

    + *

    编码时间:2020年11月25日上午8:15:29

    + *

    修改时间:2020年11月25日上午8:15:29

    + * @author 彭宇琦 + * @version Ver1.0 + * @since JDK 1.8 + * + */ +public class DataTableEventTest { + //---------------------常量区--------------------------- + /** + * 谷歌浏览器驱动文件 + */ + final File driverFile = new File("Resource/BrowersDriver/Chrom/86.0.4240.22/chromedriver.exe"); + //---------------------常量区--------------------------- + + //---------------------属性区--------------------------- + /** + * 浏览器对象 + */ + ChromeBrower brower; + /** + * 单一元素获取类对象 + */ + CommonBy cb; + /** + * 多元素获取类对象 + */ + DataListBy dlb; + /** + * 无文件存储元素信息 + */ + NoFileLocation nl; + + TextEvent te; + //---------------------属性区--------------------------- + + //---------------------待测对象区--------------------------- + /** + * 待测类对象 + */ + DataTableEvent test; + //---------------------待测对象区--------------------------- + + //---------------------数据初始化区--------------------------- + /** + * 初始化数据 + */ + @BeforeTest + public void initData() { + brower = new ChromeBrower(driverFile); + brower.addConfig(ChromeOptionType.CONTRAL_OPEN_BROWER, "127.0.0.1:9222"); + + test = new DataTableEvent(brower); + + nl = new NoFileLocation(); + + cb = new CommonBy(brower); + cb.setReadMode(nl, true); + + dlb = new DataListBy(brower); + dlb.setReadMode(nl, true); + + te = new TextEvent(brower); + } + + /** + * 用于设置数据 + */ + @BeforeClass + public void setData() { + nl.putElementLocation("上一页", ByType.XPATH, "//*[@title=\"上一页\"]"); + nl.putElementLocation("下一页", ByType.XPATH, "//*[@title=\"下一页\"]"); + + nl.putElementLocation("序号列", ByType.XPATH, "//tbody/tr/td[1]"); + nl.putElementLocation("账号列", ByType.XPATH, "//tbody/tr/td[2]"); + nl.putElementLocation("姓名列", ByType.XPATH, "//tbody/tr/td[3]"); + nl.putElementLocation("绑定手机号列", ByType.XPATH, "//tbody/tr/td[4]"); + nl.putElementLocation("是否实人认证列", ByType.XPATH, "//tbody/tr/td[5]"); + nl.putElementLocation("所属企业列", ByType.XPATH, "//tbody/tr/td[6]"); + nl.putElementLocation("创建时间列", ByType.XPATH, "//tbody/tr/td[8]"); + + test.add(dlb.find("序号列")); + test.add(dlb.find("账号列")); + test.add(dlb.find("姓名列")); + test.add(dlb.find("绑定手机号列")); + test.add(dlb.find("是否实人认证列")); + test.add(dlb.find("所属企业列")); + test.add(dlb.find("创建时间列")); + } + + /** + * 用于关闭驱动连接 + */ + @AfterClass + public void quit() { + brower.closeBrower(); + } + //---------------------数据初始化区--------------------------- + + //---------------------单元测试区--------------------------- + /** + * 用于测试{@link DataTableEvent#pageTurning(Element)}方法
    + * 预期:
    + * + */ + @Test + public void pageTurningTest() { + System.out.println(test.pageTurning(cb.getElement("上一页"))); + } + + /** + * 用于测试{@link DataTableEvent#getRowElement(int)}方法
    + * 预期:
    + * + */ + @Test + public void getRowElementTest() { + test.getRowElement(1).stream() + .map(element -> te.getText(element)) + .forEach(System.out :: println); + } + //---------------------单元测试区--------------------------- +} From 75a7795fc8255422b1f9dceed67880e859d0e16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Wed, 2 Dec 2020 08:03:06 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=B1=BB=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E4=BD=BFBy=E5=AF=B9=E8=B1=A1=E8=83=BD?= =?UTF-8?q?=E8=BF=94=E5=9B=9EElementData=E7=B1=BB=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pres/auxiliary/work/selenium/element/AbstractBy.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/pres/auxiliary/work/selenium/element/AbstractBy.java b/src/main/java/pres/auxiliary/work/selenium/element/AbstractBy.java index 43e97d3..dd2aaaf 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/AbstractBy.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/AbstractBy.java @@ -119,6 +119,14 @@ public abstract class AbstractBy { } } + /** + * 返回当前进行搜索的元素信息类({@link ElementData})对象 + * @return 元素信息类对象 + */ + public ElementData getElementData() { + return elementData; + } + /** * 该方法用于将窗体切回顶层,当本身是在最顶层时,则该方法将使用无效 */ From bff264f02abcfdde81b827d384e396ff74f43382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Fri, 4 Dec 2020 08:15:23 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E9=9B=86=E5=90=88=E9=95=BF=E5=BA=A6=E5=8F=98=E7=9F=AD=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E8=8E=B7=E5=8F=96=E9=A1=B5=E9=9D=A2=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=9C=89=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=88=E6=9B=B4=E6=94=B9=E5=BC=82=E5=B8=B8=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../work/selenium/element/Element.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/pres/auxiliary/work/selenium/element/Element.java b/src/main/java/pres/auxiliary/work/selenium/element/Element.java index 7ad1196..099d37c 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/Element.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/Element.java @@ -64,7 +64,13 @@ public class Element { againFindElement(); } - return abstractBy.elementList.get(index); + //若当前进行过重新获取元素,并且获取后其元素个数有变化,则当下标不存在时抛出异常 + try { + return abstractBy.elementList.get(index); + } catch (IndexOutOfBoundsException e) { + throw new NoSuchElementException("重新获取元素后不存在下标为“" + index + "”的元素,当前元素集合个数:" + abstractBy.elementList.size()); + } + } /** @@ -78,16 +84,13 @@ public class Element { /** * 重新根据元素信息,在页面查找元素 */ - public void againFindElement() { - //重新构造elementList -// abstractBy.elementList.clear(); -// try { -// abstractBy.elementList.addAll(abstractBy.recognitionElement(elementData)); -// }catch (TimeoutException e) { -// } + public int againFindElement() { + //重新拉取元素 abstractBy.elementList = abstractBy.recognitionElement(elementData); //切换当前读取的元素信息 abstractBy.elementData = elementData; + + return abstractBy.elementList.size(); } @Override From bd6fea0f5e8269843b2317a75ddf2ba49285efcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Sat, 5 Dec 2020 09:41:47 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=B1=BB=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/extend/ControlException.java | 47 ++ .../selenium/event/extend/DataTableEvent.java | 409 ++++++++++++------ .../event/extend/DataTableEventTest.java | 67 ++- 3 files changed, 377 insertions(+), 146 deletions(-) create mode 100644 src/main/java/pres/auxiliary/work/selenium/event/extend/ControlException.java diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/ControlException.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/ControlException.java new file mode 100644 index 0000000..ce131a5 --- /dev/null +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/ControlException.java @@ -0,0 +1,47 @@ +package pres.auxiliary.work.selenium.event.extend; + +/** + *

    文件名:ControlException.java

    + *

    用途: + * 获取控件有误时抛出的异常 + *

    + *

    编码时间:2020年11月30日上午8:37:49

    + *

    修改时间:2020年11月30日上午8:37:49

    + * @author 彭宇琦 + * @version Ver1.0 + * @since JDK 1.8 + * + */ +public class ControlException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ControlException() { + } + + public ControlException(String message) { + super(message); + } + + public ControlException(Throwable cause) { + super(cause); + } + + public ControlException(String message, Throwable cause) { + super(message, cause); + } + + public ControlException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + /** + * 用于对控件枚举不存在抛出异常时编写的基础信息 + * @param controlName 控件名称 + * @param enumName 枚举名称 + */ + public ControlException(String controlName, String enumName) { + super("“" + controlName + "”映射不存在,无法操作,需要指定枚举“" + enumName + "”的映射"); + } + +} diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java index 4b8dae0..84460fb 100644 --- a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java @@ -1,12 +1,15 @@ package pres.auxiliary.work.selenium.event.extend; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BooleanSupplier; import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; import pres.auxiliary.work.selenium.brower.AbstractBrower; import pres.auxiliary.work.selenium.element.DataListBy; @@ -15,6 +18,7 @@ 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; +import pres.auxiliary.work.selenium.event.WaitEvent; /** *

    文件名:OperateDataTable.java

    @@ -28,7 +32,7 @@ import pres.auxiliary.work.selenium.event.TextEvent; * @since JDK 1.8 * */ -public class DataTableEvent extends AbstractEvent { +public final class DataTableEvent extends AbstractEvent { /** * 用于进行点击事件 */ @@ -41,12 +45,24 @@ public class DataTableEvent extends AbstractEvent { * 用于进行断言事件 */ private AssertEvent assertEvent; + /** + * 用于进行等待事件 + */ + private WaitEvent waitEvent; /** - * 用于存储当前的列表元素 + * 用于存储当前的列表的一列元素 */ // protected ArrayList tableList = new ArrayList<>(); protected LinkedHashMap> tableMap = new LinkedHashMap<>(16); + /** + * 用于存储列表相应的操作元素映射 + */ + private HashMap controlMap = new HashMap<>(16); + /** + * 指向列表加载等待控件 + */ + private Element waitElement; /** * 用于存储当前列表的长度 @@ -69,6 +85,7 @@ public class DataTableEvent extends AbstractEvent { clickEvent = new ClickEvent(brower); textEvent = new TextEvent(brower); assertEvent = new AssertEvent(brower); + waitEvent = new WaitEvent(brower); } /** @@ -79,6 +96,14 @@ public class DataTableEvent extends AbstractEvent { public void setExamine(boolean isExamine) { this.isExamine = isExamine; } + + /** + * 用于设置列表加载等待元素,通过该元素,将应用与列表操作后,等待该控件消失后再进行断言的操作 + * @param waitElement 列表加载等待控件 + */ + public void setWaitElement(Element waitElement) { + this.waitElement = waitElement; + } /** * 用于添加一列元素,若启用严格校验(即通过{@link #setExamine(boolean)}方法设置为true), @@ -93,7 +118,7 @@ public class DataTableEvent extends AbstractEvent { * @param dataListBy 元素列查找对象 * @throws InvalidDataListException 启用严格校验且元素个数与存储列表元素个数不一致时抛出的异常 */ - public void add(DataListBy dataListBy) { + public void addList(DataListBy dataListBy) { //判断当前是否存储元素,若未存储元素,则不进行元素个数判断 if (!tableMap.isEmpty()) { //判断传入的列的元素个数是否与当前存储的元素个数一致,若不一致,则进行个数判定校验 @@ -113,7 +138,16 @@ public class DataTableEvent extends AbstractEvent { listSize = dataListBy.size(); } - tableMap.put(dataListBy.getElement(1).getElementData().getName(), dataListBy.getAllElement()); + tableMap.put(dataListBy.getElementData().getName(), dataListBy.getAllElement()); + } + + /** + * 用于添加列表控件的枚举,在调用部分列表操作方法时会使用在此处添加的映射 + * @param dataTableKeywordType 列表可映射的控件枚举{@link DataTableKeywordType} + * @param by 控件相应的元素对象{@link Element} + */ + public void putControl(DataTableKeywordType dataTableKeywordType, Element elemenet) { + controlMap.put(dataTableKeywordType, elemenet); } /** @@ -139,82 +173,84 @@ public class DataTableEvent extends AbstractEvent { } /** - * 用于点击一次上一页按钮,并返回点击成功结果 - * @param pageTurningButton 翻页按钮元素 - * @return 点击结果 - */ - public boolean pageTurning(Element pageTurningButton) { - boolean result = operateSuchAssertData(() -> { - //判断按钮是否可以点击 - if (!pageTurningButton.getWebElement().isEnabled()) { - return false; - } - - try { - clickEvent.click(pageTurningButton); - return true; - } catch (Exception e) { - return false; - } - }); - - logText = "点击“" + pageTurningButton.getElementData().getName() + "”元素,返回列表上一页,其翻页" - + (result ? "" : "不") + "成功"; - resultText = String.valueOf(result); - - return result; - } - - /** - * 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数) - * @param pageTurningButton 上一页按钮元素 + * 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 + * ,则持续翻页至无法翻页为止 * @param count 点击次数 * @return 实际点击次数 */ - public int pageTurning(Element pageTurningButton, int count) { - int nowCount = 0; - //根据设置的点击次数循环点击上一页 - while (nowCount < count) { - //若点击成功,则nowCount自增,若点击失败,则退出循环 - if (pageTurning(pageTurningButton)) { - nowCount++; - } else { - break; - } - } - - logText = "连续点击“" + pageTurningButton.getElementData().getName() + "”元素,使列表返回至上" - + count + "页,其实际翻页数为:" + nowCount; - resultText = String.valueOf(nowCount); - - //返回实际点击次数 - return nowCount; + public int previousPage(int count) { + return pageTurning(DataTableKeywordType.PREVIOUS_PAGE_BUTTON, count); } /** - * 用于持续点击上一页按钮,直到按钮不可点击为止,并返回实际点击次数(实际点击次数) - * @param pageTurningButton 上一页按钮元素 + * 用于点击多次下一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 + * ,则持续翻页至无法翻页为止 + * @param count 点击次数 * @return 实际点击次数 */ - public int continuePageTurning(Element pageTurningButton) { - int nowCount = 0; - //根据设置的点击次数循环点击上一页 - while (true) { - //若点击成功,则nowCount自增,若点击失败,则退出循环 - if (pageTurning(pageTurningButton)) { - nowCount++; - } else { - break; - } + public int nextPage(int count) { + return pageTurning(DataTableKeywordType.NEXT_PAGE_BUTTON, count); + } + + /** + * 用于对列表进行翻页操作 + * @param dataTableKeywordType 翻页按钮类型 + * @param count 指定的翻页次数 + * @return 实际翻页次数 + */ + private int pageTurning(DataTableKeywordType dataTableKeywordType, int count) { + //判断当前按钮是否存在映射 + if (!controlMap.containsKey(dataTableKeywordType)) { + throw new ControlException(dataTableKeywordType.getName(), dataTableKeywordType.toString()); } - logText = "持续点击“" + pageTurningButton.getElementData().getName() + "”元素,使列表返回至首页" - + ",其实际翻页数为:" + nowCount; + //根据设置的点击次数循环点击翻页按钮 + int nowCount = 0; + while(true) { + //判断翻页数,若当前翻页数大于指定翻页数时,则结束循环 + //若指定的翻页数小于0,则持续翻页,直到翻页失败为止 + if (nowCount >= count && count >= 0) { + break; + } + + Element controlElement = controlMap.get(dataTableKeywordType); + + boolean result = assertData(() -> { + //判断按钮是否可以点击 + if (!controlElement.getWebElement().isEnabled()) { + return false; + } + + try { + clickEvent.click(controlElement); + //等待控件消失 + if (waitElement != null) { + waitEvent.disappear(waitElement); + } + return true; + } catch (Exception e) { + return false; + } + }); + + //若点击成功,则nowCount自增,若点击失败,则退出循环 + if (!result) { + break; + } + + nowCount++; + } + + logText = "点击“" + + controlMap.get(DataTableKeywordType.PREVIOUS_PAGE_BUTTON).getElementData().getName() + + "”元素,使列表返回至" + + (dataTableKeywordType == DataTableKeywordType.PREVIOUS_PAGE_BUTTON ? "上" : "下") + + "页,其实际翻页数为:" + nowCount; resultText = String.valueOf(nowCount); //返回实际点击次数 return nowCount; - } + } /** * 用于对列表进行点击跳页按钮后的跳页操作。若当前存储过元素列表,则对元素列表进行断言, @@ -224,18 +260,38 @@ public class DataTableEvent extends AbstractEvent { * @param jumpPageButton 跳页按钮 * @param pageCountText 页码文本 */ - public boolean jumpPage(Element pageTextbox, Element jumpPageButton, String pageCount) { - boolean result = operateSuchAssertData(() -> { + public boolean jumpPage(String pageCount) { + if (!controlMap.containsKey(DataTableKeywordType.PAGE_INPUT_TEXTBOX)) { + throw new ControlException(DataTableKeywordType.PAGE_INPUT_TEXTBOX.getName() + , DataTableKeywordType.PAGE_INPUT_TEXTBOX.toString()); + } + + boolean result = assertData(() -> { //输入页码 - textEvent.input(pageTextbox, pageCount); - //点击跳页 - clickEvent.click(jumpPageButton); + textEvent.input(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX), pageCount); + //判断是否存在跳页按钮的映射,若不存在,则使用回车进行跳页 + if (controlMap.containsKey(DataTableKeywordType.JUMP_PAGE_BUTTON)) { + //点击跳页 + clickEvent.click(controlMap.get(DataTableKeywordType.JUMP_PAGE_BUTTON)); + } else { + textEvent.keyToSend(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX), Keys.ENTER); + } + + //清空输入框 + textEvent.clear(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX)); + + //等待控件消失 + if (waitElement != null) { + waitEvent.disappear(waitElement); + } return true; }); - logText = "在“" + pageTextbox.getElementData().getName() + "”元素中输入" + pageCount - + ",点击“ + jumpPageButton.getElementData().getName() + ”按钮,跳到列表相应的页码,其翻页" + logText = "在“" + + controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX).getElementData().getName() + + "”元素中输入" + pageCount + + ",使列表跳转到相应的页码,其翻页" + (result ? "" : "不") + "成功"; resultText = String.valueOf(result); @@ -243,25 +299,44 @@ public class DataTableEvent extends AbstractEvent { } /** - * 用于对列表按下回车后的跳页操作。若当前存储过元素列表,则对元素列表进行断言, - * 即取存储的列表的第一行元素,若操作前后,该行元素不变,则判定为跳页失败 + * 通过条件,点击{@link DataTableKeywordType#SEARCH_BUTTON}映射的按钮,对列表进行搜索。方法中需要接收一个 + * 返回值为boolean类型的操作,若操作的返回值为false时,则不会点击按钮,可参考以下写法: + *
    
    +	 * DataTableEvent test = new DataTableEvent(brower);
    +	 * test.searchList(() -> {
    +	 * 	te.input(cb.getElement("账号搜索文本框"), "13000000000");
    +	 * 	return true;
    +	 * });
    +	 * 
    * - * @param pageTextbox 跳页文本框元素 - * @param pageCountText 页码文本 + * @param action 返回值为boolean类型的操作 + * @return 列表是否有变化 */ - public boolean jumpPage(Element pageTextbox, String pageCount) { - boolean result = operateSuchAssertData(() -> { - //输入页码 - textEvent.input(pageTextbox, pageCount); - //点击跳页 - textEvent.keyToSend(pageTextbox, Keys.ENTER); - - return true; - }); + public boolean searchList(BooleanSupplier action) { + //判断控件是否存在 + if (!controlMap.containsKey(DataTableKeywordType.SEARCH_BUTTON)) { + throw new ControlException(DataTableKeywordType.SEARCH_BUTTON.getName() + , DataTableKeywordType.SEARCH_BUTTON.toString()); + } - logText = "在“" + pageTextbox.getElementData().getName() + "”元素中输入" + pageCount - + ",按下回车,跳到列表相应的页码,其翻页" - + (result ? "" : "不") + "成功"; + boolean result = false; + //若操作成功,则点击搜索按钮 + if (action.getAsBoolean()) { + clickEvent.click(controlMap.get(DataTableKeywordType.SEARCH_BUTTON)); + + //等待控件消失 + if (waitElement != null) { + waitEvent.disappear(waitElement); + } + + //TODO 走列表文本断言 + result = true; + } else { + result = false; + } + + logText = "通过搜索条件,点击“" + controlMap.get(DataTableKeywordType.SEARCH_BUTTON).getElementData().getName() + + "”元素,对列表进行搜索"; resultText = String.valueOf(result); return result; @@ -284,43 +359,16 @@ public class DataTableEvent extends AbstractEvent { //根据下标,获取元素,并进行存储 ArrayList elementList = new ArrayList<>(); tableMap.forEach((key, value) -> { - elementList.add(value.get(toElementIndex(listSize(key), rowIndex))); + //重新获取元素 + Element element = value.get(toElementIndex(listSize(key), rowIndex)); + element.againFindElement(); + //存储元素 + elementList.add(element); }); return elementList; } - /** - * 断言数据是否有改变,若数据改变,则返回true;反之,返回false - * @param oldElementList 原始数据元素列表 - * @param newElementList 新数据元素列表 - * @return 元素是否存在改变 - */ - protected boolean assertDataChange(ArrayList oldElementList, ArrayList 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能识别的下标 @@ -356,23 +404,20 @@ public class DataTableEvent extends AbstractEvent { * @param action 需要执行的内容 * @return 是否翻页成功 */ - private boolean operateSuchAssertData(BooleanSupplier action) { + protected boolean assertData(BooleanSupplier action) { //若元素列表非空,则获取第一行元素,用于进行断言 - ArrayList oldElementList = new ArrayList<>(); + ArrayList oldTextList = new ArrayList<>(); if (!tableMap.isEmpty()) { - //获取第一行元素 - oldElementList = getRowElement(1); + //获取第一行元素,并将其转换为文本后存储 + getRowElement(1).stream().map(textEvent :: getText).forEach(oldTextList :: add); } //执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作 if (action.getAsBoolean()) { - //获取操作后的第一行元素 - ArrayList newElementList = new ArrayList<>(); - if (!tableMap.isEmpty()) { - //获取第一行元素 - newElementList = getRowElement(1); + //若当前未获取原元素的内容,则不进行列表断言 + if (oldTextList.size() != 0) { //断言元素,并返回结果 - return assertDataChange(oldElementList, newElementList); + return assertDataChange(oldTextList); } else { return true; } @@ -381,28 +426,120 @@ public class DataTableEvent extends AbstractEvent { } } + /** + * 断言数据是否有改变,若数据改变,则返回true;反之,返回false + * @param oldTextList 原始数据文本集合 + * @param oldElement 原始数据第一个元素的{@link WebElement}对象 + * @return 元素是否存在改变 + */ + protected boolean assertDataChange(ArrayList oldTextList) { + //获取操作后的第一行元素 + ArrayList newElementList = getRowElement(1); + + //为避免不进行翻页时,列表也会进行一次刷新,则获取信息,对每个文本数据进行比对 + for (int index = 0; index < oldTextList.size(); index++) { + if (assertEvent.assertNotEqualsText(newElementList.get(index), oldTextList.get(index))) { + return true; + } + } + + return false; + } + + private void againFindDataList() { + //用于判断当前数列元素的个数 + AtomicInteger nowListSize = new AtomicInteger(-1); + tableMap.forEach((key, value) -> { + //对列表第一个元素进行重新获取 + Element element = value.get(0); + //重新获取当前元素,并存储当前列表长度 + int elementListSize = element.againFindElement(); + //判断当前size是否为初始化的状态,若为初始化的状态,则直接存储重新获取后的集合元素个数 + if (nowListSize.get() == -1) { + nowListSize.set(elementListSize); + } else { + //若当前size已被初始化,则进行重获后的元素个数判断 + if (nowListSize.get() != elementListSize) { + //若当前需要严格校验列表元素个数,则抛出异常 + if (isExamine) { + throw new InvalidDataListException("“" + key + "”元素列的元素个数与其他元素列的元素个数不一致!" + + "( “" + key + "”元素列元素列个数:" + elementListSize + "," + + "其他元素列的元素个数:" + nowListSize.get() + ")"); + } else { + //若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 + nowListSize.set(nowListSize.get() > elementListSize ? elementListSize : nowListSize.get()); + } + } + } + + //判断当前元素个数与重新获取前元素个数是否一致,不一致,则需要对数组进行处理 + + }); + } + + /** + *

    文件名:DataTableEvent.java

    + *

    用途: + * 枚举列表中可操作的控件,如上一页、下一页按钮等 + *

    + *

    编码时间:2020年11月30日上午8:03:59

    + *

    修改时间:2020年11月30日上午8:03:59

    + * @author 彭宇琦 + * @version Ver1.0 + * @since JDK 1.8 + * + */ public enum DataTableKeywordType { /** * 上一页按钮 */ - UP_PAGE_BUTTON, + PREVIOUS_PAGE_BUTTON("上一页按钮"), /** * 下一页按钮 */ - DOWN_PAGE_BUTTON, + NEXT_PAGE_BUTTON("下一页按钮"), /** * 首页按钮 */ - FIRST_PAGE_BUTTON, + FIRST_PAGE_BUTTON("首页按钮"), /** * 尾页按钮 */ - LAST_PAGE_BUTTON, + LAST_PAGE_BUTTON("尾页按钮"), /** * 跳页按钮 */ - JUMP_PAGE_BUTTON, + JUMP_PAGE_BUTTON("跳页按钮"), + /** + * 页码输入文本框(用于跳页的输入) + */ + PAGE_INPUT_TEXTBOX("页码输入文本框"), + /** + * 搜索按钮 + */ + SEARCH_BUTTON("搜索按钮") ; + + /** + * 存储枚举名称 + */ + String name; + + /** + * 初始化枚举名称 + * @param name + */ + private DataTableKeywordType(String name) { + this.name = name; + } + + /** + * 返回枚举指向的控件名称 + * @return 控件名称 + */ + public String getName() { + return name; + } } /** diff --git a/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java index 0a805e4..52824e2 100644 --- a/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java +++ b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java @@ -11,8 +11,8 @@ import pres.auxiliary.work.selenium.brower.ChromeBrower; import pres.auxiliary.work.selenium.brower.ChromeBrower.ChromeOptionType; import pres.auxiliary.work.selenium.element.CommonBy; import pres.auxiliary.work.selenium.element.DataListBy; -import pres.auxiliary.work.selenium.element.Element; import pres.auxiliary.work.selenium.event.TextEvent; +import pres.auxiliary.work.selenium.event.extend.DataTableEvent.DataTableKeywordType; import pres.auxiliary.work.selenium.location.ByType; import pres.auxiliary.work.selenium.location.NoFileLocation; @@ -21,6 +21,9 @@ import pres.auxiliary.work.selenium.location.NoFileLocation; *

    用途: * 对{@link DataTableEvent}类进行单元测试 *

    + *

    + * 环境:华建通运营端,企业用户管理界面 + *

    *

    编码时间:2020年11月25日上午8:15:29

    *

    修改时间:2020年11月25日上午8:15:29

    * @author 彭宇琦 @@ -101,14 +104,25 @@ public class DataTableEventTest { nl.putElementLocation("是否实人认证列", ByType.XPATH, "//tbody/tr/td[5]"); nl.putElementLocation("所属企业列", ByType.XPATH, "//tbody/tr/td[6]"); nl.putElementLocation("创建时间列", ByType.XPATH, "//tbody/tr/td[8]"); + nl.putElementLocation("跳页输入框", ByType.XPATH, "//*[text()='跳至']/input"); + nl.putElementLocation("加载等待", ByType.XPATH, "//div[@class=\"loader\"]"); + nl.putElementLocation("账号搜索文本框", ByType.XPATH, "//label[text()='账号']/../following-sibling :: div//input"); + nl.putElementLocation("搜索", ByType.XPATH, "//*[text()='搜 索']/.."); - test.add(dlb.find("序号列")); - test.add(dlb.find("账号列")); - test.add(dlb.find("姓名列")); - test.add(dlb.find("绑定手机号列")); - test.add(dlb.find("是否实人认证列")); - test.add(dlb.find("所属企业列")); - test.add(dlb.find("创建时间列")); + test.addList(dlb.find("序号列")); + test.addList(dlb.find("账号列")); + test.addList(dlb.find("姓名列")); + test.addList(dlb.find("绑定手机号列")); + test.addList(dlb.find("是否实人认证列")); + test.addList(dlb.find("所属企业列")); + test.addList(dlb.find("创建时间列")); + + test.putControl(DataTableKeywordType.PREVIOUS_PAGE_BUTTON, cb.getElement("上一页")); + test.putControl(DataTableKeywordType.NEXT_PAGE_BUTTON, cb.getElement("下一页")); + test.putControl(DataTableKeywordType.PAGE_INPUT_TEXTBOX, cb.getElement("跳页输入框")); + test.putControl(DataTableKeywordType.SEARCH_BUTTON, cb.getElement("搜索")); + + test.setWaitElement(cb.getElement("加载等待")); } /** @@ -122,13 +136,46 @@ public class DataTableEventTest { //---------------------单元测试区--------------------------- /** - * 用于测试{@link DataTableEvent#pageTurning(Element)}方法
    + * 用于测试{@link DataTableEvent#previousPage(int)}方法
    * 预期:
    * */ @Test public void pageTurningTest() { - System.out.println(test.pageTurning(cb.getElement("上一页"))); + System.out.println(test.previousPage(10)); + } + + /** + * 用于测试{@link DataTableEvent#nextPage(int)}方法
    + * 预期:
    + * + */ + @Test + public void nextPageTest() { + System.out.println(test.nextPage(10)); + } + + /** + * 用于测试{@link DataTableEvent#jumpPage(String)}方法
    + * 预期:
    + * + */ + @Test + public void jumpPageTest() { + System.out.println(test.jumpPage("3")); + } + + /** + * 用于测试{@link DataTableEvent#searchList(java.util.function.BooleanSupplier)}方法
    + * 预期:
    + * + */ + @Test + public void searchListTest() { + System.out.println(test.searchList(() -> { + te.input(cb.getElement("账号搜索文本框"), "13197719008"); + return true; + })); } /** From fd9fd6c36923a7fb735da562d7d8c0de9242d2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Sat, 5 Dec 2020 10:37:29 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=90=9C=E7=B4=A2=E6=96=B9=E5=BC=8F=E7=B1=BB?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pres/auxiliary/work/selenium/element/Element.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/pres/auxiliary/work/selenium/element/Element.java b/src/main/java/pres/auxiliary/work/selenium/element/Element.java index 099d37c..acf55e5 100644 --- a/src/main/java/pres/auxiliary/work/selenium/element/Element.java +++ b/src/main/java/pres/auxiliary/work/selenium/element/Element.java @@ -41,8 +41,6 @@ public class Element { this.abstractBy = abstractBy; } - - /** * 用于返回当前存储的{@link WebElement}对象,若该对象为空,则抛出元素查找超时异常 * @return {@link WebElement}对象 @@ -70,7 +68,6 @@ public class Element { } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException("重新获取元素后不存在下标为“" + index + "”的元素,当前元素集合个数:" + abstractBy.elementList.size()); } - } /** @@ -81,6 +78,14 @@ public class Element { return elementData; } + /** + * 返回当前元素的搜索方式类对象 + * @return 元素的搜索方式类对象 + */ + public AbstractBy getBy() { + return abstractBy; + } + /** * 重新根据元素信息,在页面查找元素 */ From 40ad8930200d02c1687d8f6ef532c16e61e9241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Sat, 5 Dec 2020 10:56:22 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=96=AD=E8=A8=80=E6=9C=BA=E5=88=B6=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=83=E7=B4=A0=E9=87=8D=E6=96=B0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../selenium/event/extend/DataTableEvent.java | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java index 84460fb..66537c6 100644 --- a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java @@ -359,11 +359,8 @@ public final class DataTableEvent extends AbstractEvent { //根据下标,获取元素,并进行存储 ArrayList elementList = new ArrayList<>(); tableMap.forEach((key, value) -> { - //重新获取元素 - Element element = value.get(toElementIndex(listSize(key), rowIndex)); - element.againFindElement(); //存储元素 - elementList.add(element); + elementList.add(value.get(toElementIndex(listSize(key), rowIndex))); }); return elementList; @@ -411,13 +408,16 @@ public final class DataTableEvent extends AbstractEvent { //获取第一行元素,并将其转换为文本后存储 getRowElement(1).stream().map(textEvent :: getText).forEach(oldTextList :: add); } + //获取当前集合的长度 + int oldListSize = listSize(); + //执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作 if (action.getAsBoolean()) { //若当前未获取原元素的内容,则不进行列表断言 if (oldTextList.size() != 0) { //断言元素,并返回结果 - return assertDataChange(oldTextList); + return assertDataChange(oldTextList, oldListSize); } else { return true; } @@ -432,10 +432,18 @@ public final class DataTableEvent extends AbstractEvent { * @param oldElement 原始数据第一个元素的{@link WebElement}对象 * @return 元素是否存在改变 */ - protected boolean assertDataChange(ArrayList oldTextList) { + protected boolean assertDataChange(ArrayList oldTextList, int oldListSize) { + //重新获取集合元素 + againFindDataList(); + //获取操作后的第一行元素 ArrayList newElementList = getRowElement(1); + //若集合的长度发生改变,则表示集合存在变化 + if (oldListSize != listSize) { + return true; + } + //为避免不进行翻页时,列表也会进行一次刷新,则获取信息,对每个文本数据进行比对 for (int index = 0; index < oldTextList.size(); index++) { if (assertEvent.assertNotEqualsText(newElementList.get(index), oldTextList.get(index))) { @@ -446,14 +454,21 @@ public final class DataTableEvent extends AbstractEvent { return false; } + /** + * 用于重新获取元素信息 + */ private void againFindDataList() { //用于判断当前数列元素的个数 AtomicInteger nowListSize = new AtomicInteger(-1); tableMap.forEach((key, value) -> { + //获取原集合个数 + int oldSize = value.size(); + //对列表第一个元素进行重新获取 Element element = value.get(0); //重新获取当前元素,并存储当前列表长度 int elementListSize = element.againFindElement(); + //判断当前size是否为初始化的状态,若为初始化的状态,则直接存储重新获取后的集合元素个数 if (nowListSize.get() == -1) { nowListSize.set(elementListSize); @@ -473,7 +488,14 @@ public final class DataTableEvent extends AbstractEvent { } //判断当前元素个数与重新获取前元素个数是否一致,不一致,则需要对数组进行处理 - + int nowSize = nowListSize.get(); + if (nowSize != oldSize) { + //根据元素返回的元素查找对象,强转为DataListBy后,再重新获取所有元素 + value = ((DataListBy) (element.getBy())).getAllElement(); + + //根据是否进行严格检查,来对listSize进行赋值,若无需严格检查,则取两者之间最小者 + listSize = isExamine ? nowSize : Math.min(nowSize, listSize); + } }); } From 69ad08ac60c4dbfff0f9f19739f3d181504a2051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=AE=87=E7=90=A6?= <465645774@qq.com> Date: Sat, 5 Dec 2020 17:57:04 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=B1=BB=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=88=A0=E9=99=A4=E6=97=A0=E6=95=88=E7=9A=84?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 136 +++-- .../IncorrectConditionException.java | 2 +- .../java/pres/auxiliary/tool/date/Time.java | 2 - .../tool/file/ExcelConfigXmlTool.java | 9 - .../pres/auxiliary/tool/web/Condition.java | 506 ------------------ .../auxiliary/tool/web/ConstraintType.java | 26 - .../tool/web/IncorrectFileException.java | 43 -- .../auxiliary/tool/web/WebDataCompare.java | 305 ----------- .../auxiliary/tool/web/WebDataToFile.java | 213 -------- .../selenium/event/extend/DataTableEvent.java | 425 +++++++++------ .../event/extend/DataTableEventTest.java | 20 + 11 files changed, 338 insertions(+), 1349 deletions(-) rename src/main/java/pres/auxiliary/tool/{web => date}/IncorrectConditionException.java (93%) delete mode 100644 src/main/java/pres/auxiliary/tool/web/Condition.java delete mode 100644 src/main/java/pres/auxiliary/tool/web/ConstraintType.java delete mode 100644 src/main/java/pres/auxiliary/tool/web/IncorrectFileException.java delete mode 100644 src/main/java/pres/auxiliary/tool/web/WebDataCompare.java delete mode 100644 src/main/java/pres/auxiliary/tool/web/WebDataToFile.java diff --git a/pom.xml b/pom.xml index 0ef5339..d975084 100644 --- a/pom.xml +++ b/pom.xml @@ -1,30 +1,21 @@ - - 4.0.0 + + 4.0.0 - pres.appnium.test - Autest - 0.0.1-SNAPSHOT - jar + pres.appnium.test + Autest + 0.0.1-SNAPSHOT + jar - Autest - http://maven.apache.org - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.0 - - - + Autest + http://maven.apache.org - - UTF-8 - + + UTF-8 + - + org.seleniumhq.selenium selenium-java @@ -105,69 +96,74 @@ fastjson 1.2.61 - + cn.hutool hutool-all 5.0.2 - + - com.github.noraui - ojdbc7 - 12.1.0.2 + com.github.noraui + ojdbc7 + 12.1.0.2 - + - org.apache.httpcomponents - httpclient - 4.5.12 + org.apache.httpcomponents + httpclient + 4.5.12 - + - org.jsoup - jsoup - 1.13.1 + org.jsoup + jsoup + 1.13.1 - - - - org.springframework - spring-aop - 5.2.7.RELEASE - - - org.springframework - spring-core - 5.2.7.RELEASE - - - org.aspectj - aspectjrt - 1.9.5 - - - org.aspectj - aspectjweaver - 1.9.5 - - - + + - org.projectlombok - lombok - 1.18.12 - provided + org.springframework + spring-aop + 5.2.7.RELEASE - + org.springframework + spring-core + 5.2.7.RELEASE + + + org.aspectj + aspectjrt + 1.9.5 + + + org.aspectj + aspectjweaver + 1.9.5 + + + + + org.projectlombok + lombok + 1.18.12 + provided + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + + diff --git a/src/main/java/pres/auxiliary/tool/web/IncorrectConditionException.java b/src/main/java/pres/auxiliary/tool/date/IncorrectConditionException.java similarity index 93% rename from src/main/java/pres/auxiliary/tool/web/IncorrectConditionException.java rename to src/main/java/pres/auxiliary/tool/date/IncorrectConditionException.java index 8a6d6e2..4f126ad 100644 --- a/src/main/java/pres/auxiliary/tool/web/IncorrectConditionException.java +++ b/src/main/java/pres/auxiliary/tool/date/IncorrectConditionException.java @@ -1,4 +1,4 @@ -package pres.auxiliary.tool.web; +package pres.auxiliary.tool.date; /** *

    文件名:IncorrectConditionException.java

    diff --git a/src/main/java/pres/auxiliary/tool/date/Time.java b/src/main/java/pres/auxiliary/tool/date/Time.java index bc11f3e..be0cab2 100644 --- a/src/main/java/pres/auxiliary/tool/date/Time.java +++ b/src/main/java/pres/auxiliary/tool/date/Time.java @@ -6,8 +6,6 @@ import java.util.Calendar; import java.util.Date; import java.util.regex.Pattern; -import pres.auxiliary.tool.web.IncorrectConditionException; - /** *

    * 文件名:Time.java diff --git a/src/main/java/pres/auxiliary/tool/file/ExcelConfigXmlTool.java b/src/main/java/pres/auxiliary/tool/file/ExcelConfigXmlTool.java index 52cff1a..fb0bfd9 100644 --- a/src/main/java/pres/auxiliary/tool/file/ExcelConfigXmlTool.java +++ b/src/main/java/pres/auxiliary/tool/file/ExcelConfigXmlTool.java @@ -5,7 +5,6 @@ import java.io.FileWriter; import java.io.IOException; import org.dom4j.Document; -import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; @@ -61,12 +60,4 @@ public class ExcelConfigXmlTool { writer.write(document); writer.close(); } - - private void root() { - document.setRootElement(document.addElement("templet")); - } - - private void sheet(String name, String freeze) { - Element root = document.getRootElement(); - } } diff --git a/src/main/java/pres/auxiliary/tool/web/Condition.java b/src/main/java/pres/auxiliary/tool/web/Condition.java deleted file mode 100644 index 61d27b3..0000000 --- a/src/main/java/pres/auxiliary/tool/web/Condition.java +++ /dev/null @@ -1,506 +0,0 @@ -package pres.auxiliary.tool.web; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.regex.Pattern; - -import org.openqa.selenium.WebDriver; - -/** - *

    - * 文件名:Condition.java - *

    - *

    - * 用途:用于页面统计中记录需要读取的列的定位方式 ,以及其统计的约束条件,并提供数据对比方法
    - * 注意: - *

      - *
    1. 数字和日期的边界限制,可以用中括号"[]"和小括号"()"表示,中括号表可等于,小括号表示不能等于
    2. - *
    3. 数字和日期的分段限制,用英文逗号","隔开,逗号后可以有空格也可以没有空格,但逗号前不能包含空格
    4. - *
    5. 日期类型按照[小日期,大日期)或者(小日期,大日期]的形式传入,日期的格式应为yyyy-mm-dd
    6. - *
    7. 数字类型按照[小数字,大数字)或者(小数字,大数字]的形式传入
    8. - *
    - *

    - *

    - * 编码时间:2019年7月28日下午2:13:59 - *

    - *

    - * 修改时间:2019年7月31日下午7:03:59 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 1.8 - * - */ -public class Condition { - - /** - * 用于存储元素定位方式 - */ - private String element; - /** - * 用于存储约束条件,当约束的类型为数字和日期时,此时存储的数据将是前后值是否允许包含的条件 - */ - private ArrayList constraints = new ArrayList(); - /** - * 约束类型 - */ - private ConstraintType type; - - /** - * 用于存储元素的标题 - */ - private String title; - - /** - * 用于通过列表元素定位方式获取到列表的WebElementEventList对象 - */ - private DataListEvent listEvent; - - /** - * 定义日期约束类型的传入格式 - */ - private final String REGEX_DATE = "[\\[\\(]\\d{4}[-\\.年\\\\\\/][01]?\\d[-\\.月\\\\\\/][0123]?\\d日?" - + "( [012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?)?)?, " - + "*\\d{4}[-\\.年\\\\][01]?\\d[-\\.月\\\\][0123]?\\d日?" - + "( [012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?)?)?[\\]\\)]"; - - /** - * 定义数字约束类型传入格式 - */ - private final String REGEX_NUMBER = "[\\[\\(]\\d+(.\\d+)?, *\\d+(.\\d+)?[\\]\\)]"; - - /** - * 定义日期的格式约束 - */ - private final String YEAR_TYPE = "^[-\\+]?[\\d]*$"; - - /** - * 日期和数字大小约束之间的分隔符号 - */ - private final String DATA_SEVERANCE = ";"; - - /** - * 定义边界相等的条件 - */ - private final String LIMIT_EQUALS = "1"; - - /** - * 定义边界不等的条件 - */ - private final String LIMIT_UN_EQUALS = "0"; - - /** - * 该构造用于当元素需要做约束限制进行统计时,可以使用该构造 - * - * @param title 元素标题 - * @param element 元素的定位方式 - * @param type 统计的约束类型,在{@link ConstraintType}枚举类中选择相应的约束类型 - * @param constraints 约束条件 - */ - public Condition(String title, String element, ConstraintType type, String... constraints) { - super(); - this.element = element; - this.type = type; - this.title = title; - - // 根据约束类型设置约束条件 - if (constraints != null && constraints.length != 0) { - switch (this.type) { - case STRING: - setStringConstraint(constraints); - break; - case DATE: - setDateConstraint(constraints); - break; - case NUMBER: - setNumberConstraint(constraints); - break; - default: - break; - } - } - } - - /** - * 该构造用于当元素不需要任何限制进行统计时,可使用该构造 - * - * @param title 元素标题 - * @param element 元素的定位方式 - */ - public Condition(String title, String element) { - super(); - this.element = element; - this.title = title; - } - - /** - * 该方法用于返回元素的标题 - * - * @return 元素的标题 - */ - public String getTitle() { - return title; - } - - /** - * 该方法用于返回元素的定位方式 - * - * @return 元素的定位方式 - */ - public String getElement() { - return element; - } - - /** - * 该方法用于返回传入的元素定位方式在页面上获取到的WebElementEventList对象 - * - * @param driver 页面的WebDriver对象 - * @return 返回列表的WebElementEventList对象 - */ - public DataListEvent getListEvent(WebDriver driver) { - if (listEvent == null) { - listEvent = new DataListEvent(driver); - listEvent.add(element); - } - - return listEvent; - } - - /** - * 该方法用于返回条件约束组中是否存在约束,若存在约束,则返回true,反之,返回false - * @return 返回是否存在约束条件 - */ - public boolean isConstraint() { - if (constraints.size() == 0) { - return false; - } else { - return true; - } - } - - /** - * 该方法用于判断传入的数据是否满足约束条件。若传入的数据与约束条件的类型不符合,则默认返回false - * - * @param data 待判断的数据 - * @return 是否符合约束条件 - */ - public boolean isConformToConstraint(String data) { - // 根据约束类型设置约束条件 - if (constraints != null && constraints.size() != 0) { - switch (this.type) { - case STRING: - return compareString(data); - case DATE: - return compareDate(data); - case NUMBER: - return compareNumber(data); - default: - return true; - } - } else { - return true; - } - } - - /** - * 判断数字类型数据 - * - * @param data 数据 - * @return 是否符合要求 - */ - private boolean compareNumber(String data) { - // 由于指向返回结果 - boolean a = false; - // 转换传入的数据,若抛出转换异常,则直接返回a值 - double num = 0; - - try { - num = Double.valueOf(data); - } catch (Exception e) { - return a; - } - - // 循环,读取所有的约束条件,将数据逐个和约束条件进行大小的对比 - for (String constraint : constraints) { - - // 由于约束条件中包含大小约束条件和边界的限制,故需要按照规则进行切分 - String[] ss = constraint.split(DATA_SEVERANCE); - - // 转换最大最小值 - double minNum = Double.valueOf(ss[0]); - double maxNum = Double.valueOf(ss[2]); - -// System.out.println("----------------------------"); -// System.out.println("约束最小值:" + minNum); -// System.out.println("约束最大值:" + maxNum); -// System.out.println("待测元素:" + num); - - // 对比最小值,若待测数据小于约束条件的最小值,不满足约束条件,可直接结束循环,节约时间 - if (LIMIT_EQUALS.equals(ss[1]) && LIMIT_EQUALS.equals(ss[3])) { - a = num >= minNum && num <= maxNum; - } else if (LIMIT_UN_EQUALS.equals(ss[1]) && LIMIT_EQUALS.equals(ss[3])) { - a = num > minNum && num <= maxNum; - } else if (LIMIT_EQUALS.equals(ss[1]) && LIMIT_UN_EQUALS.equals(ss[3])) { - a = num >= minNum && num < maxNum; - } else { - a = num > minNum && num < maxNum; - } - if (a) { - break; - } - } - - return a; - } - - /** - * 判断日期类型 - * - * @param data 待测数据 - * @return 是否符合约束 - */ - private boolean compareDate(String data) { - // 由于指向返回结果 - boolean a = false; - // 转换传入的数据,若抛出转换异常,则直接返回a值 - Long time = 0L; - try { - time = new SimpleDateFormat(getDateFormat(data)).parse(data).getTime(); - } catch (Exception e) { - return a; - } - - // 循环,读取所有的约束条件,将数据逐个和约束条件进行大小的对比 - for (String constraint : constraints) { - - // 由于约束条件中包含大小约束条件和边界的限制,故需要按照规则进行切分 - String[] ss = constraint.split(DATA_SEVERANCE); - - // 转换最大最小值 - double minTime = Double.valueOf(ss[0]); - double maxTime = Double.valueOf(ss[2]); - -// System.out.println("----------------------------"); -// System.out.println("约束最小值:" + minTime); -// System.out.println("约束最大值:" + maxTime); -// System.out.println("待测元素:" + time); - - // 对比最小值,若待测数据小于约束条件的最小值,不满足约束条件,可直接结束循环,节约时间 - if (LIMIT_EQUALS.equals(ss[1]) && LIMIT_EQUALS.equals(ss[3])) { - a = time >= minTime && time <= maxTime; - } else if (LIMIT_UN_EQUALS.equals(ss[1]) && LIMIT_EQUALS.equals(ss[3])) { - a = time > minTime && time <= maxTime; - } else if (LIMIT_EQUALS.equals(ss[1]) && LIMIT_UN_EQUALS.equals(ss[3])) { - a = time >= minTime && time < maxTime; - } else { - a = time > minTime && time < maxTime; - } - if (a) { - break; - } - } - - return a; - } - - /** - * 判断字符串类型 - * - * @param data 待测数据 - * @return 是否符合约束 - */ - private boolean compareString(String data) { - // 循环,读取所有的约束条件,将数据逐个和约束条件进行大小的对比 - for (String constraint : constraints) { - // 判断数据是否与约束条件相同,相同,则返回true - if (constraint.equals(data)) { - return true; - } - } - // 若数据与所有的约束都不符合,则返回false - return false; - } - - /** - * 该方法用于设置数字类型的约束条件 - * - * @param constraints 约束条件组 - */ - private void setNumberConstraint(String[] constraints) { - // 循环,逐个读取约束条件 - for (String constraint : constraints) { - // 判断传入的约束条件是否符合约束条件的传入规则,若不符合规则,则抛出IncorrectConditionException异常 - if (!Pattern.compile(REGEX_NUMBER).matcher(constraint).matches()) { - throw new IncorrectConditionException("约束条件“" + constraint + "”不符合数字约束的传入规则"); - } - - // 定义存储约束条件的字符串 - String dateConstraint = ""; - - // 按照逗号切分字符串 - String[] c = constraint.split("\\,"); - - // 将约束时段的边界提取出来 - StringBuilder cmin = new StringBuilder(c[0].trim()); - StringBuilder cmax = new StringBuilder(c[1].trim()); - - // 存储边界值的判定条件(移除该字符串则时会返回该字符串) - String minSymbox = '[' == cmin.charAt(0) ? LIMIT_EQUALS : LIMIT_UN_EQUALS; - String maxSymbox = ']' == cmax.charAt(cmax.length() - 1) ? LIMIT_EQUALS : LIMIT_UN_EQUALS; - - // 转换数字 - double minNum = 0; - double maxNum = 0; - try { - minNum = Double.valueOf(cmin.delete(0, 1).toString()); - } catch (NumberFormatException e) { - throw new IncorrectConditionException("约束条件“" + cmin + "”不符合数字约束的传入规则"); - } - - try { - maxNum = Double.valueOf(cmax.delete(cmax.length() - 1, cmax.length()).toString()); - } catch (NumberFormatException e) { - throw new IncorrectConditionException("约束条件“" + cmax + "”不符合数字约束的传入规则"); - } - - // 判断时间戳的大小,若两个时间戳大小相反,则反向存储 - if (minNum > maxNum) { - dateConstraint += (maxNum + DATA_SEVERANCE + maxSymbox + DATA_SEVERANCE + minNum + DATA_SEVERANCE - + minSymbox); - } else { - dateConstraint += (minNum + DATA_SEVERANCE + minSymbox + DATA_SEVERANCE + maxNum + DATA_SEVERANCE - + maxSymbox); - } - - this.constraints.add(dateConstraint); - } - - } - - /** - * 该方用于设置时间类型的约束条件 - * - * @param constraints 约束条件组 - */ - private void setDateConstraint(String[] constraints) { - // 循环,逐个读取约束条件 - for (String constraint : constraints) { - // 判断传入的约束条件是否符合约束条件的传入规则,若不符合规则,则抛出IncorrectConditionException异常 - if (!Pattern.compile(REGEX_DATE).matcher(constraint).matches()) { - throw new IncorrectConditionException("约束条件“" + constraint + "”不符合日期约束传入的规则"); - } - - // 定义存储约束条件的字符串 - String dateConstraint = ""; - - // 按照逗号切分字符串 - String[] c = constraint.split("\\,"); - // 将约束时段的边界提取出来 - StringBuilder cmin = new StringBuilder(c[0].trim()); - StringBuilder cmax = new StringBuilder(c[1].trim()); - - // 存储边界值的判定条件(移除该字符串则时会返回该字符串) - String minSymbox = '[' == cmin.charAt(0) ? LIMIT_EQUALS : LIMIT_UN_EQUALS; - String maxSymbox = ']' == cmax.charAt(cmax.length() - 1) ? LIMIT_EQUALS : LIMIT_UN_EQUALS; - - // 将该日期转换成时间戳,拼接至字符串中 - long minTime = 0L; - long maxTime = 0L; - try { - minTime = new SimpleDateFormat(getDateFormat(cmin.delete(0, 1).toString())).parse(cmin.toString()) - .getTime(); - } catch (ParseException e) { - throw new IncorrectConditionException("约束条件“" + cmin + "”不符合日期约束传入的规则"); - } - - try { - maxTime = new SimpleDateFormat(getDateFormat(cmax.delete(cmax.length() - 1, cmax.length()).toString())) - .parse(cmax.toString()).getTime(); - } catch (ParseException e) { - throw new IncorrectConditionException("约束条件“" + cmax + "”不符合日期约束传入的规则"); - } - - // 判断时间戳的大小,若两个时间戳大小相反,则反向存储 - if (minTime > maxTime) { - dateConstraint += (maxTime + ";" + maxSymbox + ";" + minTime + ";" + minSymbox); - } else { - dateConstraint += (minTime + ";" + minSymbox + ";" + maxTime + ";" + maxSymbox); - } - - this.constraints.add(dateConstraint); - } - } - - /** - * 该方法用于设置字符串类型的约束条件 - * - * @param constraints 约束条件组 - */ - private void setStringConstraint(String[] constraints) { - // 存储整个约束条件 - this.constraints.addAll(Arrays.asList(constraints)); - } - - /** - * 识别传入的时间格式 - * - * @param time 时间 - * @return 时间格式 - */ - private String getDateFormat(String time) { - boolean year = false; - Pattern pattern = Pattern.compile(YEAR_TYPE); - if (pattern.matcher(time.substring(0, 4)).matches()) { - year = true; - } - StringBuilder sb = new StringBuilder(); - int index = 0; - if (!year) { - if (time.contains("月") || time.contains("-") || time.contains("/")) { - if (Character.isDigit(time.charAt(0))) { - index = 1; - } - } else { - index = 3; - } - } - for (int i = 0; i < time.length(); i++) { - char chr = time.charAt(i); - if (Character.isDigit(chr)) { - if (index == 0) { - sb.append("y"); - } - if (index == 1) { - sb.append("M"); - } - if (index == 2) { - sb.append("d"); - } - if (index == 3) { - sb.append("H"); - } - if (index == 4) { - sb.append("m"); - } - if (index == 5) { - sb.append("s"); - } - if (index == 6) { - sb.append("S"); - } - } else { - if (i > 0) { - char lastChar = time.charAt(i - 1); - if (Character.isDigit(lastChar)) { - index++; - } - } - sb.append(chr); - } - } - return sb.toString(); - } -} diff --git a/src/main/java/pres/auxiliary/tool/web/ConstraintType.java b/src/main/java/pres/auxiliary/tool/web/ConstraintType.java deleted file mode 100644 index ddb7f67..0000000 --- a/src/main/java/pres/auxiliary/tool/web/ConstraintType.java +++ /dev/null @@ -1,26 +0,0 @@ -package pres.auxiliary.tool.web; - -/** - *

    文件名:ConstraintType.java

    - *

    用途:用于定义约束条件的类型

    - *

    编码时间:2019年7月28日下午2:24:40

    - *

    修改时间:2019年7月28日下午2:24:40

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 1.8 - * - */ -public enum ConstraintType { - /** - * 字符串类型 - */ - STRING, - /** - * 日期类型 - */ - DATE, - /** - * 数字类型 - */ - NUMBER -} diff --git a/src/main/java/pres/auxiliary/tool/web/IncorrectFileException.java b/src/main/java/pres/auxiliary/tool/web/IncorrectFileException.java deleted file mode 100644 index 6773ed9..0000000 --- a/src/main/java/pres/auxiliary/tool/web/IncorrectFileException.java +++ /dev/null @@ -1,43 +0,0 @@ -package pres.auxiliary.tool.web; - -/** - *

    文件名:IncorrectFileException.java

    - *

    用途:用于读取的文件与相应的代码不匹配时弹出的异常

    - *

    编码时间:2019年8月2日下午5:33:01

    - *

    修改时间:2019年8月2日下午5:33:01

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 1.8 - * - */ -public class IncorrectFileException extends RuntimeException { - - private static final long serialVersionUID = -5513588664798256321L; - - public IncorrectFileException() { - super(); - // TODO Auto-generated constructor stub - } - - public IncorrectFileException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - // TODO Auto-generated constructor stub - } - - public IncorrectFileException(String message, Throwable cause) { - super(message, cause); - // TODO Auto-generated constructor stub - } - - public IncorrectFileException(String message) { - super(message); - // TODO Auto-generated constructor stub - } - - public IncorrectFileException(Throwable cause) { - super(cause); - // TODO Auto-generated constructor stub - } - -} diff --git a/src/main/java/pres/auxiliary/tool/web/WebDataCompare.java b/src/main/java/pres/auxiliary/tool/web/WebDataCompare.java deleted file mode 100644 index 20362e7..0000000 --- a/src/main/java/pres/auxiliary/tool/web/WebDataCompare.java +++ /dev/null @@ -1,305 +0,0 @@ -package pres.auxiliary.tool.web; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.LinkedHashMap; - -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openqa.selenium.WebDriver; - -/** - *

    - * 文件名:WebDataCompare.java - *

    - *

    - * 用途:用于对页面数据的操作工具 - *

    - *

    - * 编码时间:2019年8月2日上午9:45:00 - *

    - *

    - * 修改时间:2019年8月3日上午10:42:00 - *

    - * - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 1.8 - * - */ -public class WebDataCompare { - /** - * 定义文件中的换行符 - */ - private static final String FILE_LINK = "\r\n"; - - /** - * 存储用户传入的WebDriver对象,当为null时,则使用默认的WebDriver对象,若用户定义时,则使用定义的WebDriver对象 - */ - private static WebDriver driver = null; - - /** - * 该方法用于设置WebDriver对象 - * @param driver WebDriver对象 - */ - public static void setWebDriver(WebDriver driver) { - WebDataCompare.driver = driver; - } - - /** - * 该方法用于统计页面数据,根据数据的约束条件进行数据的组合统计,并将统计存储指定的excel文件中 - * - * @param folder 文件保存的文件夹 - * @param fileName 文件名 - * @param conditions 条件类对象组 - * @param iframes 需要定位到列表所在的窗体 - * @return 统计结果文件 - * @throws IOException - */ - public static File statisData(File folder, String fileName, Condition[] conditions, String... iframes) - throws IOException { - Event event = null; - if (driver == null) { - // 构造事件类对象 - event = Event.newInstance(new ChromeBrower("resource/BrowserDriver/chromedriver.exe", 9222).getDriver()); - // 循环,添加所有的iframe - for (String iframe : iframes) { - event.switchFrame(iframe); - } - } else { - event = Event.newInstance(driver); - } - - // 定义map对象,用于记录列表数据 - LinkedHashMap> datas = new LinkedHashMap>(); - // 定义map,用于存储组合条件的数据 - LinkedHashMap groupDatas = new LinkedHashMap(); - - // 创建文件夹 - folder.mkdirs(); - // 定义目标文件 - File targeFile = new File(folder, ("\\" + fileName + ".xlsx")); - // 判断文件是否存在,若文件存在,则读取文件 - if (targeFile.exists()) { - // 循环,抽取title,用于指定Sheet的名称,并存储该Sheet - for (Condition condition : conditions) { - // 构造统计map - datas.put(condition, readFile(targeFile, condition.getTitle(), 1, 0, 1)); - } - - // 存储组合条件的map - groupDatas = readFile(targeFile, "组合条件", 1, 0, 1); - } else { - // 循环,抽取title,构造map - for (Condition condition : conditions) { - // 构造统计map - datas.put(condition, new LinkedHashMap()); - } - } - - // 指定当前获取列表的行数 - int index = 0; - // 循环,获取页面每一行的数据 - while (true) { - // 用于指定循环是否继续 - boolean hasData = true; - // 用于判断数据是否符合约束条件 - boolean constraint = true; - // 用于存储组合查询符合约束条件的元素值 - String constraintText = ""; - - // 循环,datas中存储的所有的Condition对象,以用于获取一行数据 - for (Condition condition : datas.keySet()) { - try { - // 读取第index行数据 - String text = condition.getListEvent(event.getDriver()).getEvent(condition.getElement(), index).getText().getStringValve(); - // 判断该数据是否存在于condition指向的Map,若存在,则其Integer加1,不存在,则put如Map - if (datas.get(condition).containsKey(text)) { - datas.get(condition).put(text, datas.get(condition).get(text) + 1); - } else { - datas.get(condition).put(text, 1); - } - - //判断condition中是否存储了约束条件,若无约束条件,则无需判断 - if (condition.isConstraint()) { - // 判断constraint是否已经为false,若已经为false,则表示某一列的元素已经不符合约束,则无需再对比其他列的数据 - if (!constraint) { - continue; - } else { - // 若constraint为true,则对比当前列的数据是否符合约束,并将返回值存储至constraint中 - if (constraint = condition.isConformToConstraint(text)) { - constraintText += (condition.getTitle() + ":" + text + FILE_LINK); - } else { - //当constraint为false时,则直接将constraintText置为空,以便于之后存储判断 - constraintText = ""; - } - } - } - // 判断该值是否符合约束条件 - } catch (IndexOutOfBoundsException e) { - // 若列表元素已被全部读取,则此会抛出IndexOutOfBoundsException,则可直接结束循环 - hasData = false; - break; - } - } - // 判断hasData值,若hasData为false,则表示此时列表上某一列或所有列的数据读取完毕,则可以结束外层循环 - if (!hasData) { - break; - } - // 判断需要存储的约束条件是否为空,若为空,则不进行存储 - //注意,其为空只会有两种情况: - //1.constraint为true,但condition不存在约束条件,此时,循环中不走约束条件的判断,导致constraint恒为true,但constraintText仍为初始空值 - //2.condition存在约束,但其中一个元素未通过约束判断,导致constraintText置为了空值 - //故此处应用constraintText是否为空作为存储至map的条件依据 - if (!constraintText.isEmpty()) { - constraintText = constraintText.substring(0, constraintText.length() - FILE_LINK.length()); - if (groupDatas.containsKey(constraintText)) { - groupDatas.put(constraintText, groupDatas.get(constraintText) + 1); - } else { - groupDatas.put(constraintText, 1); - } - } - - // 初始化数据 - index++; - constraintText = ""; - } - - //循环,读取datas中存储的所有的数据,将其一一写入文件中 - for (Condition condition : datas.keySet()) { - writeFile(targeFile, datas.get(condition), condition.getTitle(), 0, 0, 1); - } - - if (groupDatas.size() != 0) { - writeFile(targeFile, groupDatas, "组合条件", 0, 0, 1); - } - - //若使用默认的WebDriver对象,则关闭其对象 - if (driver == null) { - event.getDriver().quit(); - } - - //打开文件夹 - java.awt.Desktop.getDesktop().open(folder); - return targeFile; - } - - /** - * 该方法用于将读取到的列表文件存储至文件中 - * @param targeFile 目标文件 - * @param datas 存储了数据的map类对象 - * @param sheetName 需要写入的Sheet名称 - * @param dataRow 从哪一行开始写 - * @param keyCell 标题列 - * @param valueCell 数据值列 - * @throws IOException - */ - private static void writeFile(File targeFile, LinkedHashMap datas, String sheetName, int dataRow, - int keyCell, int valueCell) throws IOException { - // 定义xlsx操作类对象,若文件存在则续写,文件不存在则新写 - XSSFWorkbook xlsx = null; - XSSFSheet sheet = null; - //判断文件是否存在,若文件不存在,则创建xlsx文件,若文件存在,则按照指定的数据读取xlsx - if (targeFile.exists()) { - xlsx = new XSSFWorkbook(new FileInputStream(targeFile)); - //判断sheet是否存在,若sheet不存在,则创建sheet - if ((sheet = xlsx.getSheet(sheetName)) == null) { - sheet = xlsx.createSheet(sheetName); - } - } else { - xlsx = new XSSFWorkbook(); - sheet = xlsx.createSheet(sheetName); - } - //创建标题行 - XSSFRow xr = sheet.createRow(dataRow++); - xr.createCell(keyCell).setCellValue("列表值"); - xr.createCell(valueCell).setCellValue("出现次数"); - - //设置单元格自动换行并垂直居中 - XSSFCellStyle xcs = xlsx.createCellStyle(); - xcs.setWrapText(true); - xcs.setVerticalAlignment(VerticalAlignment.CENTER); - - //循环,读取map中所有的元素 - for (String data : datas.keySet()) { - //创建一行数据,并将行数向下移 - xr = sheet.createRow(dataRow++); - //创建并存储列表值及出现次数 - xr.createCell(keyCell).setCellValue(data); - xr.getCell(keyCell).setCellStyle(xcs); - xr.createCell(valueCell).setCellValue(datas.get(data)); - xr.getCell(valueCell).setCellStyle(xcs); - } - - //添加筛选项 - sheet.setAutoFilter(CellRangeAddress.valueOf((String.valueOf((char) (65 + keyCell - 1)) - + "1:" + String.valueOf((char) (65 + keyCell)) - + "1"))); - - sheet.setAutoFilter(CellRangeAddress.valueOf((String.valueOf((char) (65 + valueCell - 1)) - + "1:" + String.valueOf((char) (65 + valueCell)) - + "1"))); - - //写入文件 - xlsx.write(new FileOutputStream(targeFile)); - //关闭流 - xlsx.close(); - } - - /** - * 该方法用于读取指定的excel文件,将其转换成map进行返回 - * @param targeFile 目标文件 - * @param sheetName 需要读取的Sheet名 - * @param dataRow 从哪一行开始读取 - * @param keyCell key所在的列 - * @param valueCell value所在的列 - * @return 返回LinkedHashMap对象 - * @throws IOException - */ - private static LinkedHashMap readFile(File targeFile, String sheetName, int dataRow, int keyCell, - int valueCell) throws IOException { - //存储获取到的数据 - LinkedHashMap map = new LinkedHashMap(); - - XSSFWorkbook xlsx = new XSSFWorkbook(new FileInputStream(targeFile)); - //判断sheet是否存在,若sheet不存在,则创建sheet - XSSFSheet sheet = xlsx.getSheet(sheetName); - if (sheet == null) { - xlsx.close(); - return map; - } - - //循环,读取所有的行 - for (int i = dataRow; i < sheet.getLastRowNum() + 1; i++) { - //读取相应的key和value,put入map中 - String key = ""; - try { - key = sheet.getRow(i).getCell(keyCell).toString(); - } catch (NullPointerException e) { - xlsx.close(); - throw new IncorrectFileException("文件读取错误,指定的行数:" + keyCell + "不存在"); - } - int value = 0; - try { - String s = sheet.getRow(i).getCell(valueCell).toString(); - value = Integer.valueOf(s.substring(0, s.indexOf("."))); - } catch (NumberFormatException e) { - xlsx.close(); - throw new IncorrectFileException("统计数据“" + sheet.getRow(i).getCell(valueCell).toString() + "”无法转换成数字"); - } catch (NullPointerException e) { - xlsx.close(); - throw new IncorrectFileException("文件读取错误,指定的行数:" + valueCell + "不存在"); - } - map.put(key, value); - } - - xlsx.close(); - return map; - } -} diff --git a/src/main/java/pres/auxiliary/tool/web/WebDataToFile.java b/src/main/java/pres/auxiliary/tool/web/WebDataToFile.java deleted file mode 100644 index c752a02..0000000 --- a/src/main/java/pres/auxiliary/tool/web/WebDataToFile.java +++ /dev/null @@ -1,213 +0,0 @@ -package pres.auxiliary.tool.web; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.xwpf.usermodel.XWPFDocument; - -/** - *

    文件名:WebDataToFile.java

    - *

    用途:用于从页面爬取数据以文本的形式存储至本地的工具

    - *

    编码时间:2019年7月19日下午5:04:20

    - *

    修改时间:2019年7月20日下午6:17:20

    - * @author 彭宇琦 - * @version Ver1.0 - * @since JDK 1.8 - * - */ -public class WebDataToFile { - /** - * 定义元素行间的分隔方式 - */ - private static final String LINE = "\n"; - - /** - * 该方法可用于获取页面的数据,并以docx的文件形式进行存储 - * @param folder 生成的文件存放位置 - * @param fileName 生成的文件名 - * @param element 需要获取文本的元素 - * @param iframes 定位到元素前所需进入的iframe - * @return 返回生成的文件对象 - * @throws IOException - */ - public static File webTextDataToFile(File folder, String fileName, String element, String... iframes) throws IOException { - //定义浏览器对象,该对象暂时定义为已开启的浏览器对象 - Event event = Event.newInstance(new ChromeBrower("resource/BrowserDriver/chromedriver.exe", 9222).getDriver()); - - //循环,添加所有的框架 - for (String iframe : iframes) { - event.switchFrame(iframe); - } - - //获取页面数据 - String text = event.getTextEvent().getText(element).getStringValve().trim(); - - //返回生成的文件的文件对象 - return writeData(folder, fileName, text, false); - } - - /** - * 该方法可用于获取页面列表上的一页数据,并以xlsx的文件形式进行存储 - * @param folder 生成的文件存放位置 - * @param fileName 生成的文件名 - * @param title 列表的标题 - * @param element 元素的定位方式 - * @param iframes 定位到元素前所需进入的iframe - * @return 返回生成的文件对象 - * @throws IOException - */ - public static File webListDataToFile(File folder, String fileName, String title, String element, String... iframes) throws IOException { - //定义事件类,用于定位iframe - Event event = Event.newInstance(new ChromeBrower("resource/BrowserDriver/chromedriver.exe", 9222).getDriver()); - - //循环,添加所有的框架 - for (String iframe : iframes) { - event.switchFrame(iframe); - } - - //定义列表元素操作类对象 - DataListEvent listEvent = new DataListEvent(event.getDriver()); - //存储从页面上获取到的元素,并存储传入的标题 - String text = title + LINE; - - //获取页面列表数据 - listEvent.add(element); - //循环,将获取到的文本存储至text中 - for(ListEvent e : listEvent.getEvents(element)) { - text += (e.getText().getStringValve() + LINE); - } - - //返回生成的文件的文件对象 - return writeData(folder, fileName, text, true); - } - - /** - * 该方法用于将数据写入相应的文件中 - * @param targeFile 目标文件对象 - * @param text 需要写入文件的文本 - * @param list 定义写入数据的方式是否为列表 - * @return 生成的文件对象 - * @throws IOException - */ - private static File writeData(File folder, String fileName, String text, boolean list) throws IOException { - //创建文件夹 - folder.mkdirs(); - File targeFile = null; - - //判断写入数据的方式是否为列表,为列表,则按照excel形式存储,为文本则按照docx形式存储 - if (list) { - //定义需要存储的目标文件 - targeFile = new File(folder + "\\" + fileName + ".xlsx"); - //打开文件夹 - java.awt.Desktop.getDesktop().open(folder); - return writeXlsx(targeFile, text); - } else { - //定义需要存储的目标文件 - targeFile = new File(folder + "\\" + fileName + ".docx"); - //打开文件夹 - java.awt.Desktop.getDesktop().open(folder); - return writeDocx(targeFile, text); - } - } - - /** - * 用于对docx文本的写入 - * @param targeFile 目标文件 - * @param text 文本 - * @return 生成的文件对象 - * @throws IOException - */ - private static File writeDocx(File targeFile, String text) throws IOException { - //定义docx操作类对象,若文件存在则续写,文件不存在则新写 - XWPFDocument docx = null; - if (targeFile.exists()) { - docx = new XWPFDocument(new FileInputStream(targeFile)); - } else { - docx = new XWPFDocument(); - } - - //创建新的段落,并写入text中的内容 - docx.createParagraph().createRun().setText(text); - docx.write(new FileOutputStream(targeFile)); - docx.close(); - - return targeFile; - } - - /** - * 用于对xlsx文本的写入 - * @param targeFile 目标文件 - * @param text 文本 - * @return 生成的文件 - */ - private static File writeXlsx(File targeFile, String text) throws IOException { - //切割内容,便于后续的存储 - String[] texts = text.split("\\n"); - - //定义xlsx操作类对象,若文件存在则续写,文件不存在则新写 - XSSFWorkbook xlsx = null; - XSSFSheet sheet = null; - //定义需要写入文件中的行和列,用于指向文本内容在文件中的某列的某行写入 - int row = 0; - int cell = 0; - //定义循环时需要从texts的哪一个元素开始循环读取 - int i = 0; - if (targeFile.exists()) { - xlsx = new XSSFWorkbook(new FileInputStream(targeFile)); - sheet = xlsx.getSheetAt(0); - - //获取文件的标题,用于判断该标题是否存在于文件中 - String title = texts[0].trim(); - //循环,读取文件中标题行的所有列,以对比标题是否存在 - for (; cell < sheet.getRow(0).getLastCellNum(); cell++) { - //对比标题是否存在,若存在,则结束循环,则可以得到cell的值 - if (sheet.getRow(0).getCell(cell).toString().equals(title)) { - break; - } - - } - - //判断当前需要写入的列是否为最后一列,若为不为最后一列,则不需要记录标题列,其i值设为1,表示从texts的第二个元素读取 - //并记录从哪一行开始写入数据 - if (cell != sheet.getRow(0).getLastCellNum()) { - i = 1; - //循环,判断当前的应从当前列的哪一行开始写入数据 - //需要注意的是,此处去sheet中的最大行数作为循环结束的标志,这是因为文本中最长的列为sheet.getLastRowNum(),若该列的数据 - //相较sheet.getLastRowNum()短时则直接结束循环,其结束的row + 1便是可写入数据的行 - for (; row < sheet.getLastRowNum(); row++) { - if (sheet.getRow(row).getCell(cell) == null) { - row--; - break; - } - } - System.out.println(row); - - row++; - } - } else { - //由于文件不存在,则不需要计算任何的循环值(row、cell、i都为0) - xlsx = new XSSFWorkbook(); - sheet = xlsx.createSheet(); - } - - //写入数据 - for (; i < texts.length; i++, row++) { - XSSFRow xr = null; - //判断当前行是否存在,存在则不创新创建,以免清空之前的数据 - if ((xr = sheet.getRow(row)) == null) { - xr = sheet.createRow(row); - } - xr.createCell(cell).setCellValue(texts[i]); - } - - xlsx.write(new FileOutputStream(targeFile)); - xlsx.close(); - - return targeFile; - } -} diff --git a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java index 66537c6..377b811 100644 --- a/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java +++ b/src/main/java/pres/auxiliary/work/selenium/event/extend/DataTableEvent.java @@ -21,12 +21,19 @@ import pres.auxiliary.work.selenium.event.TextEvent; import pres.auxiliary.work.selenium.event.WaitEvent; /** - *

    文件名:OperateDataTable.java

    - *

    用途: - * 提供对数据表格进行基本操作的事件,包括对数据列表的翻页、跳页、获取等操作,以简化部分操作的代码 + *

    + * 文件名:OperateDataTable.java *

    - *

    编码时间:2020年11月17日上午7:58:40

    - *

    修改时间:2020年11月17日上午7:58:40

    + *

    + * 用途: 提供对数据表格进行基本操作的事件,包括对数据列表的翻页、跳页、获取等操作,以简化部分操作的代码 + *

    + *

    + * 编码时间:2020年11月17日上午7:58:40 + *

    + *

    + * 修改时间:2020年11月17日上午7:58:40 + *

    + * * @author 彭宇琦 * @version Ver1.0 * @since JDK 1.8 @@ -49,7 +56,7 @@ public final class DataTableEvent extends AbstractEvent { * 用于进行等待事件 */ private WaitEvent waitEvent; - + /** * 用于存储当前的列表的一列元素 */ @@ -63,17 +70,17 @@ public final class DataTableEvent extends AbstractEvent { * 指向列表加载等待控件 */ private Element waitElement; - + /** * 用于存储当前列表的长度 */ protected int listSize = -1; - + /** * 标记是否进行元素个数长度校验 */ protected boolean isExamine = true; - + /** * 构造对象 * @@ -81,24 +88,26 @@ public final class DataTableEvent extends AbstractEvent { */ public DataTableEvent(AbstractBrower brower) { super(brower); - + clickEvent = new ClickEvent(brower); textEvent = new TextEvent(brower); assertEvent = new AssertEvent(brower); waitEvent = new WaitEvent(brower); } - + /** * 用于设置是否对传入的元素列表的个数进行严格校验,即在调用{@link #add(DataListBy)}方法时, * 若元素个数与初次传入的个数不符且需要严格校验,则抛出异常;反之,则直接进行存储 + * * @param isExamine 是否严格校验元素个数 */ public void setExamine(boolean isExamine) { this.isExamine = isExamine; } - + /** * 用于设置列表加载等待元素,通过该元素,将应用与列表操作后,等待该控件消失后再进行断言的操作 + * * @param waitElement 列表加载等待控件 */ public void setWaitElement(Element waitElement) { @@ -108,64 +117,70 @@ public final class DataTableEvent extends AbstractEvent { /** * 用于添加一列元素,若启用严格校验(即通过{@link #setExamine(boolean)}方法设置为true), * 则调用该方法时将对存储的数据个数进行校验,若传入的列元素个数与当前存储的列表元素个数 - * 不一致时,则抛出{@link InvalidDataListException}异常 + * 不一致时,则抛出{@link InvalidDataListException}异常。 * *

    - * 注意:传入的{@link DataListBy}类对象中元素的名称请勿与其他元素名称一致,否则会 - * 覆盖原有的元素列 + * 注意:传入的{@link DataListBy}类对象中元素的名称请勿与其他元素名称一致,否则会覆盖原有的元素列。 + * 其元素名称将作为列表名称,可通过该名称获取当前列 *

    * * @param dataListBy 元素列查找对象 * @throws InvalidDataListException 启用严格校验且元素个数与存储列表元素个数不一致时抛出的异常 */ public void addList(DataListBy dataListBy) { - //判断当前是否存储元素,若未存储元素,则不进行元素个数判断 + // 判断当前是否存储元素,若未存储元素,则不进行元素个数判断 if (!tableMap.isEmpty()) { - //判断传入的列的元素个数是否与当前存储的元素个数一致,若不一致,则进行个数判定校验 + // 判断传入的列的元素个数是否与当前存储的元素个数一致,若不一致,则进行个数判定校验 int nowSize = dataListBy.size(); if (nowSize != listSize()) { - //若当前需要严格校验列表元素个数,则抛出异常 + // 若当前需要严格校验列表元素个数,则抛出异常 if (isExamine) { - throw new InvalidDataListException("当前传入的元素列个数与存储的元素列个数不一致!" - + "(当前元素列个数:" + listSize() + ",传入的元素列元素个数:" + nowSize + ")"); + throw new InvalidDataListException( + "当前传入的元素列个数与存储的元素列个数不一致!" + "(当前元素列个数:" + listSize() + ",传入的元素列元素个数:" + nowSize + ")"); } else { - //若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 + // 若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 listSize = listSize < nowSize ? listSize : nowSize; } } - + } else { listSize = dataListBy.size(); } - + tableMap.put(dataListBy.getElementData().getName(), dataListBy.getAllElement()); } - + /** * 用于添加列表控件的枚举,在调用部分列表操作方法时会使用在此处添加的映射 + * * @param dataTableKeywordType 列表可映射的控件枚举{@link DataTableKeywordType} - * @param by 控件相应的元素对象{@link Element} + * @param by 控件相应的元素对象{@link Element} */ public void putControl(DataTableKeywordType dataTableKeywordType, Element elemenet) { controlMap.put(dataTableKeywordType, elemenet); } - + /** - * 返回元素列中元素的个数,若设置了严格判断,则该数值为所有列的元素个数;反之,则该 - * 数值表示列表集合中,最短元素列的元素个数 + * 返回元素列中元素的个数,若设置了严格判断,则该数值为所有列的元素个数;反之,则该 数值表示列表集合中,最短元素列的元素个数 * * @return 元素列的元素个数 */ public int listSize() { return listSize; } - + + /** + * 获取列表名称指向列的元素个数 + * @param name 列表名称 + * @return 指向的列表元素个数 + */ public int listSize(String name) { return tableMap.get(name).size(); } - + /** * 用于返回元素表中的列数 + * * @return */ public int rowSize() { @@ -173,57 +188,58 @@ public final class DataTableEvent extends AbstractEvent { } /** - * 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 - * ,则持续翻页至无法翻页为止 + * 用于点击多次上一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 ,则持续翻页至无法翻页为止 + * * @param count 点击次数 * @return 实际点击次数 */ public int previousPage(int count) { return pageTurning(DataTableKeywordType.PREVIOUS_PAGE_BUTTON, count); } - + /** - * 用于点击多次下一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 - * ,则持续翻页至无法翻页为止 + * 用于点击多次下一页按钮,并返回实际点击次数(实际点击次数)。若设置的翻页次数小于0 ,则持续翻页至无法翻页为止 + * * @param count 点击次数 * @return 实际点击次数 */ public int nextPage(int count) { return pageTurning(DataTableKeywordType.NEXT_PAGE_BUTTON, count); } - + /** * 用于对列表进行翻页操作 + * * @param dataTableKeywordType 翻页按钮类型 - * @param count 指定的翻页次数 + * @param count 指定的翻页次数 * @return 实际翻页次数 */ private int pageTurning(DataTableKeywordType dataTableKeywordType, int count) { - //判断当前按钮是否存在映射 + // 判断当前按钮是否存在映射 if (!controlMap.containsKey(dataTableKeywordType)) { throw new ControlException(dataTableKeywordType.getName(), dataTableKeywordType.toString()); } - - //根据设置的点击次数循环点击翻页按钮 + + // 根据设置的点击次数循环点击翻页按钮 int nowCount = 0; - while(true) { - //判断翻页数,若当前翻页数大于指定翻页数时,则结束循环 - //若指定的翻页数小于0,则持续翻页,直到翻页失败为止 + while (true) { + // 判断翻页数,若当前翻页数大于指定翻页数时,则结束循环 + // 若指定的翻页数小于0,则持续翻页,直到翻页失败为止 if (nowCount >= count && count >= 0) { break; } - + Element controlElement = controlMap.get(dataTableKeywordType); - - boolean result = assertData(() -> { - //判断按钮是否可以点击 + + boolean result = assertData(() -> { + // 判断按钮是否可以点击 if (!controlElement.getWebElement().isEnabled()) { return false; } - + try { clickEvent.click(controlElement); - //等待控件消失 + // 等待控件消失 if (waitElement != null) { waitEvent.disappear(waitElement); } @@ -232,120 +248,117 @@ public final class DataTableEvent extends AbstractEvent { return false; } }); - - //若点击成功,则nowCount自增,若点击失败,则退出循环 + + // 若点击成功,则nowCount自增,若点击失败,则退出循环 if (!result) { break; } - + nowCount++; } - - logText = "点击“" - + controlMap.get(DataTableKeywordType.PREVIOUS_PAGE_BUTTON).getElementData().getName() - + "”元素,使列表返回至" - + (dataTableKeywordType == DataTableKeywordType.PREVIOUS_PAGE_BUTTON ? "上" : "下") + + logText = "点击“" + controlMap.get(DataTableKeywordType.PREVIOUS_PAGE_BUTTON).getElementData().getName() + + "”元素,使列表返回至" + (dataTableKeywordType == DataTableKeywordType.PREVIOUS_PAGE_BUTTON ? "上" : "下") + "页,其实际翻页数为:" + nowCount; resultText = String.valueOf(nowCount); - - //返回实际点击次数 + + // 返回实际点击次数 return nowCount; - } - + } + /** * 用于对列表进行点击跳页按钮后的跳页操作。若当前存储过元素列表,则对元素列表进行断言, * 即取存储的列表的第一行元素,若操作前后,该行元素不变,则判定为跳页失败 * - * @param pageTextbox 跳页文本框元素 + * @param pageTextbox 跳页文本框元素 * @param jumpPageButton 跳页按钮 - * @param pageCountText 页码文本 + * @param pageCountText 页码文本 */ public boolean jumpPage(String pageCount) { if (!controlMap.containsKey(DataTableKeywordType.PAGE_INPUT_TEXTBOX)) { - throw new ControlException(DataTableKeywordType.PAGE_INPUT_TEXTBOX.getName() - , DataTableKeywordType.PAGE_INPUT_TEXTBOX.toString()); + throw new ControlException(DataTableKeywordType.PAGE_INPUT_TEXTBOX.getName(), + DataTableKeywordType.PAGE_INPUT_TEXTBOX.toString()); } - + boolean result = assertData(() -> { - //输入页码 + // 输入页码 textEvent.input(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX), pageCount); - //判断是否存在跳页按钮的映射,若不存在,则使用回车进行跳页 + // 判断是否存在跳页按钮的映射,若不存在,则使用回车进行跳页 if (controlMap.containsKey(DataTableKeywordType.JUMP_PAGE_BUTTON)) { - //点击跳页 + // 点击跳页 clickEvent.click(controlMap.get(DataTableKeywordType.JUMP_PAGE_BUTTON)); } else { textEvent.keyToSend(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX), Keys.ENTER); } - - //清空输入框 + + // 清空输入框 textEvent.clear(controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX)); - - //等待控件消失 + + // 等待控件消失 if (waitElement != null) { waitEvent.disappear(waitElement); } - + return true; }); - - logText = "在“" - + controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX).getElementData().getName() - + "”元素中输入" + pageCount - + ",使列表跳转到相应的页码,其翻页" - + (result ? "" : "不") + "成功"; + + logText = "在“" + controlMap.get(DataTableKeywordType.PAGE_INPUT_TEXTBOX).getElementData().getName() + "”元素中输入" + + pageCount + ",使列表跳转到相应的页码,其翻页" + (result ? "" : "不") + "成功"; resultText = String.valueOf(result); - + return result; } - + /** * 通过条件,点击{@link DataTableKeywordType#SEARCH_BUTTON}映射的按钮,对列表进行搜索。方法中需要接收一个 * 返回值为boolean类型的操作,若操作的返回值为false时,则不会点击按钮,可参考以下写法: - *
    
    +	 * 
    +	 * 
    +	 * 
     	 * DataTableEvent test = new DataTableEvent(brower);
     	 * test.searchList(() -> {
     	 * 	te.input(cb.getElement("账号搜索文本框"), "13000000000");
     	 * 	return true;
     	 * });
    -	 * 
    + *
    + *
    * * @param action 返回值为boolean类型的操作 * @return 列表是否有变化 */ public boolean searchList(BooleanSupplier action) { - //判断控件是否存在 + // 判断控件是否存在 if (!controlMap.containsKey(DataTableKeywordType.SEARCH_BUTTON)) { - throw new ControlException(DataTableKeywordType.SEARCH_BUTTON.getName() - , DataTableKeywordType.SEARCH_BUTTON.toString()); + throw new ControlException(DataTableKeywordType.SEARCH_BUTTON.getName(), + DataTableKeywordType.SEARCH_BUTTON.toString()); } - - boolean result = false; - //若操作成功,则点击搜索按钮 - if (action.getAsBoolean()) { - clickEvent.click(controlMap.get(DataTableKeywordType.SEARCH_BUTTON)); - - //等待控件消失 - if (waitElement != null) { - waitEvent.disappear(waitElement); + + boolean result = assertData(() -> { + // 若操作成功,则点击搜索按钮 + if (action.getAsBoolean()) { + clickEvent.click(controlMap.get(DataTableKeywordType.SEARCH_BUTTON)); + + // 等待控件消失 + if (waitElement != null) { + waitEvent.disappear(waitElement); + } + + return true; + } else { + return false; } - - //TODO 走列表文本断言 - result = true; - } else { - result = false; - } - + }); + logText = "通过搜索条件,点击“" + controlMap.get(DataTableKeywordType.SEARCH_BUTTON).getElementData().getName() + "”元素,对列表进行搜索"; resultText = String.valueOf(result); - + return result; } - + /** *

    - * 获取指定的一行元素,下标允许传入负数,表示从后向前遍历,具体遍历逻辑 - * 可参考{@link DataListBy#getElement(int)}方法。 + * 获取指定的一行元素,下标允许传入负数,表示从后向前遍历,具体遍历逻辑可参考{@link DataListBy#getElement(int)}方法。 *

    *

    * 注意:下标将按照元素列长度进行计算,若下标的绝对值大于元素列长度,且下标为正数,则 @@ -356,19 +369,68 @@ public final class DataTableEvent extends AbstractEvent { * @return 指定行的元素集合 */ public ArrayList getRowElement(int rowIndex) { - //根据下标,获取元素,并进行存储 + // 根据下标,获取元素,并进行存储 ArrayList elementList = new ArrayList<>(); tableMap.forEach((key, value) -> { - //存储元素 + // 存储元素 elementList.add(value.get(toElementIndex(listSize(key), rowIndex))); }); - + return elementList; } + + /** + * 获取指定行的文本,其行号可传入负数,具体规则可参考{@link DataListBy#getElement(int)}方法 + * @param rowIndex 指定的行号 + * @return 该行元素的文本 + */ + public ArrayList getRowText(int rowIndex) { + //重新获取列表元素 + againFindDataList(); + + ArrayList rowTextList = new ArrayList<>(); + // 遍历元素,将其转换为文本后进行存储 + getRowElement(rowIndex).stream().map(textEvent::getText).forEach(rowTextList :: add); + + //添加日志 + resultText = rowTextList.toString(); + logText = "获取列表第" + rowIndex + "行元素内容的文本,其获取到的文本内容为:" + resultText; + + return rowTextList; + } /** - * 由于方法允许传入负数和特殊数字0为下标,并且下标的序号由1开始, - * 故可通过该方法对下标的含义进行转义,得到java能识别的下标 + * 获取指定列的文本,若该列元素异常时,则抛出异常 + * @param listName 列表名称 + * @return 指定列的文本内容 + * @throws ControlException 该列不存在或该列元素为空时抛出的异常 + */ + public ArrayList getListText(String listName) { + //重新获取列表元素 + againFindDataList(); + + //判断列元素是否存在,若不存在,则抛出异常 + if (!tableMap.containsKey(listName)) { + throw new ControlException("“" + listName + "”指向的列元素不存在"); + } + //判断当前列是否包含元素 + if (listSize(listName) == 0) { + throw new ControlException("“" + listName + "”指向的列无元素"); + } + + ArrayList listTextList = new ArrayList<>(); + // 遍历元素,将其转换为文本后进行存储 + tableMap.get(listName).stream().map(textEvent::getText).forEach(listTextList :: add); + + //添加日志 + resultText = listTextList.toString(); + logText = "获取列表的" + listName + "列元素内容的文本,其获取到的文本内容为:" + resultText; + + return listTextList; + } + + /** + * 由于方法允许传入负数和特殊数字0为下标,并且下标的序号由1开始, 故可通过该方法对下标的含义进行转义,得到java能识别的下标 * * @param length 元素的个数 * @param index 传入的下标 @@ -395,28 +457,28 @@ public final class DataTableEvent extends AbstractEvent { return new Random().nextInt(length); } } - + /** * 用于执行需要断言页面元素的列表操作,在其操作方法前后添加了断言操作 + * * @param action 需要执行的内容 * @return 是否翻页成功 */ protected boolean assertData(BooleanSupplier action) { - //若元素列表非空,则获取第一行元素,用于进行断言 + // 若元素列表非空,则获取第一行元素,用于进行断言 ArrayList oldTextList = new ArrayList<>(); if (!tableMap.isEmpty()) { - //获取第一行元素,并将其转换为文本后存储 - getRowElement(1).stream().map(textEvent :: getText).forEach(oldTextList :: add); + // 获取第一行元素,并将其转换为文本后存储 + getRowElement(1).stream().map(textEvent::getText).forEach(oldTextList::add); } - //获取当前集合的长度 + // 获取当前集合的长度 int oldListSize = listSize(); - - - //执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作 + + // 执行操作,并获取操作的返回结果;若返回值为true,则需要进行元素断言操作 if (action.getAsBoolean()) { - //若当前未获取原元素的内容,则不进行列表断言 + // 若当前未获取原元素的内容,则不进行列表断言 if (oldTextList.size() != 0) { - //断言元素,并返回结果 + // 断言元素,并返回结果 return assertDataChange(oldTextList, oldListSize); } else { return true; @@ -425,87 +487,94 @@ public final class DataTableEvent extends AbstractEvent { return false; } } - + /** * 断言数据是否有改变,若数据改变,则返回true;反之,返回false + * * @param oldTextList 原始数据文本集合 - * @param oldElement 原始数据第一个元素的{@link WebElement}对象 + * @param oldElement 原始数据第一个元素的{@link WebElement}对象 * @return 元素是否存在改变 */ protected boolean assertDataChange(ArrayList oldTextList, int oldListSize) { - //重新获取集合元素 + // 重新获取集合元素 againFindDataList(); - - //获取操作后的第一行元素 + + // 获取操作后的第一行元素 ArrayList newElementList = getRowElement(1); - - //若集合的长度发生改变,则表示集合存在变化 + + // 若集合的长度发生改变,则表示集合存在变化 if (oldListSize != listSize) { return true; } - - //为避免不进行翻页时,列表也会进行一次刷新,则获取信息,对每个文本数据进行比对 + + // 为避免不进行翻页时,列表也会进行一次刷新,则获取信息,对每个文本数据进行比对 for (int index = 0; index < oldTextList.size(); index++) { if (assertEvent.assertNotEqualsText(newElementList.get(index), oldTextList.get(index))) { return true; } } - + return false; } - + /** * 用于重新获取元素信息 */ private void againFindDataList() { - //用于判断当前数列元素的个数 + // 用于判断当前数列元素的个数 AtomicInteger nowListSize = new AtomicInteger(-1); tableMap.forEach((key, value) -> { - //获取原集合个数 + // 获取原集合个数 int oldSize = value.size(); - - //对列表第一个元素进行重新获取 + + // 对列表第一个元素进行重新获取 Element element = value.get(0); - //重新获取当前元素,并存储当前列表长度 + // 重新获取当前元素,并存储当前列表长度 int elementListSize = element.againFindElement(); - - //判断当前size是否为初始化的状态,若为初始化的状态,则直接存储重新获取后的集合元素个数 + + // 判断当前size是否为初始化的状态,若为初始化的状态,则直接存储重新获取后的集合元素个数 if (nowListSize.get() == -1) { - nowListSize.set(elementListSize); + nowListSize.set(elementListSize); } else { - //若当前size已被初始化,则进行重获后的元素个数判断 + // 若当前size已被初始化,则进行重获后的元素个数判断 if (nowListSize.get() != elementListSize) { - //若当前需要严格校验列表元素个数,则抛出异常 + // 若当前需要严格校验列表元素个数,则抛出异常 if (isExamine) { - throw new InvalidDataListException("“" + key + "”元素列的元素个数与其他元素列的元素个数不一致!" - + "( “" + key + "”元素列元素列个数:" + elementListSize + "," - + "其他元素列的元素个数:" + nowListSize.get() + ")"); + throw new InvalidDataListException("“" + key + "”元素列的元素个数与其他元素列的元素个数不一致!" + "( “" + key + + "”元素列元素列个数:" + elementListSize + "," + "其他元素列的元素个数:" + nowListSize.get() + ")"); } else { - //若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 + // 若无需校验元素个数,则判断传入的元素个数与存储的元素列个数,存储较小的数字 nowListSize.set(nowListSize.get() > elementListSize ? elementListSize : nowListSize.get()); } } } - - //判断当前元素个数与重新获取前元素个数是否一致,不一致,则需要对数组进行处理 + + // 判断当前元素个数与重新获取前元素个数是否一致,不一致,则需要对数组进行处理 int nowSize = nowListSize.get(); if (nowSize != oldSize) { - //根据元素返回的元素查找对象,强转为DataListBy后,再重新获取所有元素 + // 根据元素返回的元素查找对象,强转为DataListBy后,再重新获取所有元素 value = ((DataListBy) (element.getBy())).getAllElement(); - - //根据是否进行严格检查,来对listSize进行赋值,若无需严格检查,则取两者之间最小者 + + // 根据是否进行严格检查,来对listSize进行赋值,若无需严格检查,则取两者之间最小者 listSize = isExamine ? nowSize : Math.min(nowSize, listSize); } }); } - + /** - *

    文件名:DataTableEvent.java

    - *

    用途: - * 枚举列表中可操作的控件,如上一页、下一页按钮等 + *

    + * 文件名:DataTableEvent.java *

    - *

    编码时间:2020年11月30日上午8:03:59

    - *

    修改时间:2020年11月30日上午8:03:59

    + *

    + * 用途: 枚举列表中可操作的控件,如上一页、下一页按钮等 + *

    + *

    + * 编码时间:2020年11月30日上午8:03:59 + *

    + *

    + * 修改时间:2020年11月30日上午8:03:59 + *

    + * * @author 彭宇琦 * @version Ver1.0 * @since JDK 1.8 @@ -515,33 +584,32 @@ public final class DataTableEvent extends AbstractEvent { /** * 上一页按钮 */ - PREVIOUS_PAGE_BUTTON("上一页按钮"), + PREVIOUS_PAGE_BUTTON("上一页按钮"), /** * 下一页按钮 */ - NEXT_PAGE_BUTTON("下一页按钮"), + NEXT_PAGE_BUTTON("下一页按钮"), /** * 首页按钮 */ - FIRST_PAGE_BUTTON("首页按钮"), + FIRST_PAGE_BUTTON("首页按钮"), /** * 尾页按钮 */ - LAST_PAGE_BUTTON("尾页按钮"), + LAST_PAGE_BUTTON("尾页按钮"), /** * 跳页按钮 */ - JUMP_PAGE_BUTTON("跳页按钮"), + JUMP_PAGE_BUTTON("跳页按钮"), /** * 页码输入文本框(用于跳页的输入) */ - PAGE_INPUT_TEXTBOX("页码输入文本框"), + PAGE_INPUT_TEXTBOX("页码输入文本框"), /** * 搜索按钮 */ - SEARCH_BUTTON("搜索按钮") - ; - + SEARCH_BUTTON("搜索按钮"); + /** * 存储枚举名称 */ @@ -549,6 +617,7 @@ public final class DataTableEvent extends AbstractEvent { /** * 初始化枚举名称 + * * @param name */ private DataTableKeywordType(String name) { @@ -557,20 +626,28 @@ public final class DataTableEvent extends AbstractEvent { /** * 返回枚举指向的控件名称 + * * @return 控件名称 */ public String getName() { return name; } } - + /** - *

    文件名:DataTableEvent.java

    - *

    用途: - * 若元素列表无法添加时抛出的异常 + *

    + * 文件名:DataTableEvent.java *

    - *

    编码时间:2020年11月19日下午8:26:49

    - *

    修改时间:2020年11月19日下午8:26:49

    + *

    + * 用途: 若元素列表无法添加时抛出的异常 + *

    + *

    + * 编码时间:2020年11月19日下午8:26:49 + *

    + *

    + * 修改时间:2020年11月19日下午8:26:49 + *

    + * * @author 彭宇琦 * @version Ver1.0 * @since JDK 1.8 @@ -599,6 +676,6 @@ public final class DataTableEvent extends AbstractEvent { public InvalidDataListException(Throwable cause) { super(cause); } - + } } diff --git a/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java index 52824e2..cac837c 100644 --- a/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java +++ b/src/test/java/pres/auxiliary/work/selenium/event/extend/DataTableEventTest.java @@ -189,5 +189,25 @@ public class DataTableEventTest { .map(element -> te.getText(element)) .forEach(System.out :: println); } + + /** + * 用于测试{@link DataTableEvent#getRowText(int)}方法
    + * 预期:
    + * + */ + @Test + public void getRowTextTest() { + test.getRowText(2).forEach(System.out :: println); + } + + /** + * 用于测试{@link DataTableEvent#getListText(String)}方法
    + * 预期:
    + * + */ + @Test + public void getListTextTest() { + test.getListText("账号列").forEach(System.out :: println); + } //---------------------单元测试区--------------------------- }