无论是Python里的Beautifu Report还是Java中的ZTestReport,仔细阅读源码发现已经实现了诸多非常便利的方法,虽然源码中很多写法冗余和耦合都很严重,但仍旧可以满足普通的使用者,但是对高级使用者而言完全可以修改源码重新编译

ZTestReport

package util;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;import org.testng.IReporter;
import org.testng.IResultMap;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.xml.XmlSuite;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;public class TestReport_original implements IReporter {// 定义生成测试报告的路径和文件名,为兼容Windows和Linux此处使用File.separator代替分隔符private String path = System.getProperty("user.dir")+File.separator+"report.html";// 定义html样式模板所在路径private String templatePath = System.getProperty("user.dir")+File.separator+"template";private int testsPass = 0;private int testsFail = 0;private int testsSkip = 0;private String beginTime;private long totalTime;private String name;public TestReport_original(){SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmssSSS");name = formatter.format(System.currentTimeMillis());}public TestReport_original(String name){this.name = name;if(this.name==null){SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmssSSS");this.name = formatter.format(System.currentTimeMillis());}}@Overridepublic void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {List<ITestResult> list = new ArrayList<ITestResult>();for (ISuite suite : suites) {Map<String, ISuiteResult> suiteResults = suite.getResults();for (ISuiteResult suiteResult : suiteResults.values()) {ITestContext testContext = suiteResult.getTestContext();IResultMap passedTests = testContext.getPassedTests();testsPass = testsPass + passedTests.size();IResultMap failedTests = testContext.getFailedTests();testsFail = testsFail + failedTests.size();IResultMap skippedTests = testContext.getSkippedTests();testsSkip = testsSkip + skippedTests.size();IResultMap failedConfig = testContext.getFailedConfigurations();list.addAll(this.listTestResult(passedTests));list.addAll(this.listTestResult(failedTests));list.addAll(this.listTestResult(skippedTests));list.addAll(this.listTestResult(failedConfig));}}this.sort(list);this.outputResult(list);}private ArrayList<ITestResult> listTestResult(IResultMap resultMap) {Set<ITestResult> results = resultMap.getAllResults();return new ArrayList<ITestResult>(results);}private void sort(List<ITestResult> list) {Collections.sort(list, new Comparator<ITestResult>() {@Overridepublic int compare(ITestResult r1, ITestResult r2) {if (r1.getStartMillis() > r2.getStartMillis()) {return 1;} else {return -1;}}});}private void outputResult(List<ITestResult> list) {try {List<ReportInfo> listInfo = new ArrayList<ReportInfo>();int index = 0;for (ITestResult result : list) {String tn = result.getTestContext().getCurrentXmlTest().getParameter("testCase");if(index==0){SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");beginTime = formatter.format(new Date(result.getStartMillis()));index++;}long spendTime = result.getEndMillis() - result.getStartMillis();totalTime += spendTime;String status = this.getStatus(result.getStatus());List<String> log = Reporter.getOutput(result);for (int i = 0; i < log.size(); i++) {log.set(i, log.get(i).replaceAll("\"", "\\\\\""));}Throwable throwable = result.getThrowable();if(throwable!=null){log.add(throwable.toString().replaceAll("\"", "\\\\\""));StackTraceElement[] st = throwable.getStackTrace();for (StackTraceElement stackTraceElement : st) {log.add(("    " + stackTraceElement).replaceAll("\"", "\\\\\""));}}ReportInfo info = new ReportInfo();info.setName(tn);info.setSpendTime(spendTime+"ms");info.setStatus(status);info.setClassName(result.getInstanceName());info.setMethodName(result.getName());info.setDescription(result.getMethod().getDescription());info.setLog(log);listInfo.add(info);}Map<String, Object> result = new HashMap<String, Object>();result.put("testName", name);result.put("testPass", testsPass);result.put("testFail", testsFail);result.put("testSkip", testsSkip);result.put("testAll", testsPass+testsFail+testsSkip);result.put("beginTime", beginTime);result.put("totalTime", totalTime+"ms");result.put("testResult", listInfo);Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();String template = this.read(templatePath);BufferedWriter output = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(new File(path)),"UTF-8"));template = template.replaceFirst("\\$\\{resultData\\}", Matcher.quoteReplacement(gson.toJson(result)));output.write(template);output.flush();output.close();} catch (IOException e) {e.printStackTrace();}}private String getStatus(int status) {String statusString = null;switch (status) {case 1:statusString = "成功";break;case 2:statusString = "失败";break;case 3:statusString = "跳过";break;default:break;}return statusString;}public static class ReportInfo {private String name;private String className;private String methodName;private String description;private String spendTime;private String status;private List<String> log;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public String getMethodName() {return methodName;}public void setMethodName(String methodName) {this.methodName = methodName;}public String getSpendTime() {return spendTime;}public void setSpendTime(String spendTime) {this.spendTime = spendTime;}public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}public List<String> getLog() {return log;}public void setLog(List<String> log) {this.log = log;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}}private String read(String path) {File file = new File(path);InputStream is = null;StringBuffer sb = new StringBuffer();try {is = new FileInputStream(file);int index = 0;byte[] b = new byte[1024];while ((index = is.read(b)) != -1) {sb.append(new String(b, 0, index));}return sb.toString();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}}return null;}
}

测试代码

package testscript;import java.lang.reflect.Method;import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import util.TestReport;@Listeners({TestReport.class})
public class Demo_How_to_use_TestReport {@BeforeMethod(description="测试方法前初始化")public void beforeMethod(Method m){if("testDemo3".equals(m.getName())){int a = 1/0;System.out.println(a);}}@Test(description="测试DEMO")public void testDemo(){Reporter.log("this is demo!");int a = 1/0;System.out.println(a);Assert.assertEquals("a", "b", "should be equals.");} @Test(description="测试DEMO1")public void testDemo1(){Reporter.log("this is demo!");Assert.assertEquals("a", "b", "should be equals.");} @Test(description="测试DEMO2",dataProvider="test")public void testDemo2(int a){Reporter.log("this is demo!");Assert.assertEquals(a, 1, "should be equals.");} @Test(description="测试DEMO3")public void testDemo3(){Reporter.log("this is demo!");Assert.assertEquals("a", "a", "should be equals.");} @DataProvider(name="test")public Object[][] dataProvider(){return new Object[][]{{1},{2}};}}

Java自动化测试系列[v1.0.1][ZTestReport测试报告]相关推荐

  1. Java自动化测试系列[v1.0.0][TestNG测试开发环境配置]

    基于之前写的一篇文章Java自动化测试系列[v1.0.0][Maven开发环境]的基础上,阐述如何配置单元测试框架TestNG的测试开发环境 创建Maven项目 启动IDEA,点击Create New ...

  2. Java自动化测试系列[v1.0.0][ZTestReport测试报告]

    获取报告框架 ZTestReport 源码Clone地址为ZTestReport ,其中ZTestReport.java和其template是我们需要的关键 修改报告框架 根据我的需要,在源码基础上进 ...

  3. Java自动化测试系列[v1.0.0][自动化测试框架理念]

    自动化测试含义 在自动化测试领域内流传着一个说法:单元测试才是自动化测试的核心,在自动化测试里,无论框架何等完美都不可能脱离单元测试,单元测试将会是自动化测试里最小的单位,把它看作单位一,若干个单位一 ...

  4. Java面向对象系列[v1.0.0][类加载器]

    类加载器负责将.class文件加载到内存中,并为它生成对应的java.lang.Class对象 类加载机制 类加载器负责加载所有的类,并未所有被载入内存中的类生成一个java.lang.Class实例 ...

  5. JavaApp自动化测试系列[v1.0.0][Appium开发环境搭建]

    Appium 是一个开源工具,用于自动化 iOS 手机. Android 手机和 Windows 桌面平台上的原生.移动 Web 和混合应用.「原生应用」指那些用 iOS. Android 或者 Wi ...

  6. Java面向对象系列[v1.0.0][SQL语法之DDL]

    SQL语法基础 SQL全称是Structured Query Language也就是结构化查询语言,它是操作和检索关系数据库的标准语言,标准的SQL语句可以用于操作任何关系数据库,标准的SQL语句通常 ...

  7. Python自动化测试系列[v1.0.0][Win32模拟键盘]

    在实际的自动化代码调试过程中,往往Selenium提供的方法不能满足于自动化任务,例如定位某个按钮要完成点击操作,定位正确但就是无法完成点击,此时如果掌握模拟键盘的方法便可以为我们的自动化提供很大的帮 ...

  8. Java面向对象系列[v1.0.0][泛型基础]

    Java5增加泛型支持,很大程度上是为了让集合记住其元素的数据类型,在此之前不用泛型的话,一旦把一个对象放进Java集合中,集合就会忘记对象的类型,把所有的对象当成Object类型处理,从集合里取出对 ...

  9. Java面向对象系列[v1.0.0][泛型进阶]

    所谓泛型,就是允许在定义类.接口.方法时使用类型形参,这个类型形参(或者叫泛型)将在声明变量.创建对象.调用方法时动态地指定(即传入实际的类型参数也可称为类型实参) Java5改写了集合框架中的全部接 ...

  10. Java面向对象系列[v1.0.0][SQL语法之数据库约束]

    数据库约束 所有关系型数据库都支持对数据表使用约束,在表面上是强制执行的数据校验规则,通过约束可以更好的的保证数据表里数据的完整性 大部分数据库支持5中完整性约束 NOT NULL:非空约束,指定某列 ...

最新文章

  1. 毕业后的五年拉开大家差距的原因在哪里?
  2. DGL教程【二】如何通过DGL表示一个Graph
  3. 气泡提示效果css.html,用纯CSS3绘制高端简约的气泡提示框
  4. vsm java_java – 我尝试使用JAXB将对象编组到xml文件中时,错误为“缺少@XmlRootElement注释”...
  5. php计算代码运行时间与内存使用的一段代码
  6. Linux平台提取DSDT,手动提取DSDT和SSDT教程
  7. 阿里云 Aliplayer高级功能介绍(四):直播时移
  8. 微软神操作!Web 版 VS Code 来了!
  9. CassiniDev源码学习 - 可替代IIS的单机Web Form解决方案
  10. selenium python 文本框输入信息_selenium python向富文本框中输入内容
  11. PPT图片快速编辑技巧
  12. 不同服务器数据库之间的数据操作
  13. android剪贴板数据来源,Android判断程序回到前台并获取剪贴板数据
  14. 水晶报表的学习与开发
  15. Delete出错分析总结(个人总结很到位) 0x0000007ff64426f87e(ucrtbased.dll)处(处于dataa.exe中)引发的异常:
  16. Spring5之IOC容器中IOC操作之Bean管理(二)之p名称空间注入、外部bean、内部bean、级联赋值
  17. Python多维数组,已知多科成绩求英语成绩最高的学生名
  18. Excel里面输入18位数字,但是显示却是其他的?!请问怎么解决?
  19. 什么叫MD5,MD5通常做什么用处,为什么MD5不可逆,用做密码加密的时候仍然可能会被解密?
  20. corex9服务器组装攻略,超频极速散热 Tt Core X9水冷最佳拍档

热门文章

  1. Nginx——自定义错误页面
  2. 移远BC26使用总结
  3. 怎么把pdf拆分成一页一页的?
  4. 搜狗输入法纯净_最新PC端搜狗输入法,无广告弹窗纯净版
  5. 华为路由器ensp静态路由配置实例
  6. Delphi组件介绍
  7. php视频格式转换mp4教程,PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
  8. 未来生活进行时: 畅想未来新兴技术40年——百大趋势性技术汇总(上)
  9. 《数字电子技术基础》6.3 时序逻辑电路——寄存器、计数器及脉冲发生器功能介绍
  10. 计算机vb题库程序代码编写,11计算机专业VB试题(二)