文章目录

我在做 java 的 WebUI 自动化测试的时候,会要求生成测试报告,用 testng 自带的测试报告,样式太丑了,因此需要使用其他的模板样式,这里我考虑使用 BeautifulReport 报告模板样式,其实对于 python 来说可以直接 pip BeautifulReport 来做,当然这里我介绍的是 java 项目

这里展示一下 BeautifulReport 模板样式

第一步:maven 配置依赖
WebUI 项目中其实 selenium 依赖 testng 依赖都应该有,下面这个 extentreports 是用来做定制模板的依赖

<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.14.3</version>
</dependency>
<dependency><groupId>com.aventstack</groupId><artifactId>extentreports</artifactId><version>3.0.7</version>
</dependency>

第二步:编写测试报告监听器类
我在项目下src/test/java/com/abcnull/listener添加了一个测试报告监听器类 TestReportListener,它继承自 testng 依赖包中的 IReporter。TestReportListener 中其实没用到太多 extentreports 依赖中的 API,只有 Gson 类来自 extentreports 依赖中,基本还是靠着第三步中写好的 BeautifulReport 型式的 html 模板,代码如下:

package com.abcnull.listener;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.testng.*;
import org.testng.xml.XmlSuite;import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;/*** @author abcnull* @version 1.0.0* @date 2020/1/26*/
public class TestReportListener implements IReporter {// 日期格式化private static Date date = new Date();private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd,HH点mm分ss秒");private static String reportdate = simpleDateFormat.format(date);private static String getReportName = "自动化测试报告-" + reportdate;// 定义html模板所在路径private String templatePath = this.getClass().getResource("/").getPath() + "report/template.html";// 定义报告生成的路径private String reportDirPath = System.getProperty("user.dir") + File.separator + "target" + File.separator + "test-output" + File.separator + "report";private String reportPath = reportDirPath + File.separator + getReportName + ".html";private String name = "DemoTest";private int testsPass;private int testsFail;private int testsSkip;private String beginTime;private long totalTime;private String project = "WebUI自动化测试报告";@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) {return r1.getStartMillis() < r2.getStartMillis() ? -1 : 1;}});}public long getTime() {return totalTime;}private void outputResult(List<ITestResult> list) {try {List<ReportInfo> listInfo = new ArrayList<ReportInfo>();int index = 0;for (ITestResult result : list) {String testName = result.getTestContext().getCurrentXmlTest().getName();if (index == 0) {SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");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(testName);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);System.out.println("!@#= 运行时间为" + totalTime + "################");result.put("testName", this.project);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(reportDirPath, templatePath);BufferedWriter output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(reportPath)), "UTF-8"));template = template.replace("${resultData}", 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 reportDirPath, String templatePath) {//文件夹不存在时级联创建目录File reportDir = new File(reportDirPath);if (!reportDir.exists() && !reportDir.isDirectory()) {reportDir.mkdirs();}File templateFile = new File(templatePath);InputStream inputStream = null;StringBuffer stringBuffer = new StringBuffer();try {inputStream = new FileInputStream(templateFile);int index = 0;byte[] b = new byte[1024];while ((index = inputStream.read(b)) != -1) {stringBuffer.append(new String(b, 0, index));}return stringBuffer.toString();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}return null;}
}

当然这个监听器代码中很多地方可以做定制化修改

第三步:testng.xml 配置测试报告监听器
在 testng.xml 中配置上监听器如下:

<listeners><listener class-name="com.abcnull.listener.TestReportListener"/>
</listeners>

第四步:项目添加 html 测试报告模板
src/test/resources/report中添加了 template.html 测试报告模板,模板使用了在线版 bootstrap,完整 html 文件会在此博文中上传资源附件,不用担心下载此附件消耗 0 积分!

template.html 附件下载地址

这个 template.html 模板会在测试报告监听器中指定用什么报告模板


第五步:查看测试报告
由于项目是 maven 项目,测试完用例之后我们可以在target/test-output/report下查看到新产生的 html 测试报告
当然这个报告生成的路径也是可以在测试报告监听器中指定的

java testng 中使用 BeautifulReport 测试报告模板相关推荐

  1. Python中使用BeautifulReport形成测试报告教程

    Python中使用BeautifulReport形成测试报告教程 pyton中使用BeautifulReport形成测试报告需要先安装BeautifulReport模块 打开cmd窗口输入 pip i ...

  2. IDEA下,如何在java项目中新增jsp模板文件

    IDEA下,如何在java项目中新增jsp模板文件 大家会不会有这样的烦恼,就是当想要创建一个jsp模板文件的时候,右键new的时候找不到JSP选项. 这是因为在创建项目的时候没有选中Web Appl ...

  3. Java项目中利用Freemarker模板引擎导出--生成Word文档

    应邀写的一篇文章:Java项目中利用Freemarker模板引擎导出--生成Word文档 资源下载:https://download.csdn.net/download/weixin_41367523 ...

  4. thymeleaf 调用java,thymeleaf模板引擎调用java类中的方法(附源码)

    前言 由于开源了项目的缘故,很多使用了My Blog项目的朋友遇到问题也都会联系我去解决,有的是把问题留在项目的issue里提出,有的是在我的私人博客里留言,还有的则是直接添加我的qq来找我讲自己遇到 ...

  5. Java使用poi加载Excel模板,将查询出来的数据封装到Excel中并进行指定某些列的合并操作

    Java使用poi加载Excel模板,将查询出来的数据封装到Excel中并进行指定某些列的合并操作 最近一周项目中需要读取数据库中的记录将记录封装到给定的模板中,指定业务列需要进行合并:下面将它进行整 ...

  6. 使用java+TestNG进行接口回归测试

    TestNG是一个开源自动化测试框架,TestNG表示下一代(Next Generation的首字母). TestNG类似于JUnit(特别是JUnit 4),但它不是JUnit框架的扩展,相较于Ju ...

  7. java+testng接口测试入门

    testNG是一个测试框架,它能组织测试用例按照你想要的方式进行运行,并输出一定格式的便于阅读的测试报告(结果),通过java+testng的方式说明一下接口测试的基本使用方法. 一.环境搭建 a)千 ...

  8. 使用java+TestNG进行接口回归测试 1

    [技术沙龙002期]数据中台:宜信敏捷数据中台建设实践|宜信技术沙龙 将于5月23日晚8点线上直播,点击报名 TestNG是一个开源自动化测试框架,"NG"表示下一代(Next G ...

  9. java接口自动化Excel占位符_基于maven+java+TestNG+httpclient+poi+jsonpath+ExtentReport的接口自动化测试框架...

    接口自动化框架 项目说明 本框架是一套基于maven+java+TestNG+httpclient+poi+jsonpath+ExtentReport而设计的数据驱动接口自动化测试框架,TestNG ...

最新文章

  1. plasma桌面设置好的面板消失了_Ubuntu Studio 将用 KDE Plasma 桌面环境替换 Xfce | Linux 中国...
  2. 数字图像基本处理算法小结
  3. linux uname 命令详解
  4. 算法提高课-动态规划-树形DP-AcWing 1072. 树的最长路径:dfs写法
  5. numpy 和tensorflow中argmax(),argmin()函数使用讲解
  6. ABAP的OPEN SQL和Hybris Commerce的Flexible Search简介
  7. csv文件设置每个cell大小_Python对文本文件和Excel的处理机制
  8. LeetCode 965. 单值二叉树
  9. 深圳大学二本计算机软件,深圳大学是几本(深圳大学是一本还是二本)
  10. js对象扁平化:Javascript对象进行扁平化处理
  11. python二级考试笔记_Python二级考试临时抱佛脚专用笔记——(一)数据表示与计算...
  12. 【习题5】用Python完成新建文档写古诗+复制
  13. 电商基本功:被小瞧的促销设计,并没有想得那么简单
  14. 汽车零部件-线控底盘
  15. Spring设置定时任务时,关于执行时间的规则设置
  16. Adobe国际认证证书有什么用?
  17. uniApp消息推送(极光/阿里云)
  18. 3.创建项目并初始化业务数据(电商推荐系统)
  19. Android手机连接蓝牙打印机连接不上的问题
  20. oracle 12C没有hr_main.sql脚本文件,无法创建sample schema

热门文章

  1. java的包装类不可变_为什么像java中的布尔类包装类是不可变的?
  2. redis 持续时间_Redis性能指标监控!你知道多少?
  3. Unity 3D 新手强烈推荐教程
  4. EQ均衡器及常见声音频段
  5. 【从零学Python】深拷贝和浅拷贝、二维数组初始化
  6. 【电气专业知识问答】问:如何实现变压器电压的调节?调压分接开关的类型和特点是什么?各适用在哪些场合?
  7. 深入支付宝支付扫描支付-跳转支付宝二维码页面支付与自定义生成二维码支付-1参数配置篇
  8. 三进制计算机_来了!中级综合能力常考知识点集锦(三)
  9. 2021上系统集成项目管理工程师报考条件、报考时间、考试安排
  10. 技术赋能:数字化转型的最佳实践