博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
测试报告 之 testNG + Velocity 编写自定义html测试报告
阅读量:7011 次
发布时间:2019-06-28

本文共 19190 字,大约阅读时间需要 63 分钟。

之前用testNG自带的test-outputemailable-report.html,做出的UI自动化测试报告,页面不太好看。

在网上找到一个新的报告编写,自己尝试了一下,埋了一些坑,修改了输出时间格式,最终出的结果比以前稍好。

简单介绍下Velocity

1.不用像jsp那样编译成servlet(.Class)文件,直接装载后就可以运行了,装载的过程在web.xml里面配置。【后缀名为.vhtml是我们自己的命名方式。也只有在这里配置了哪种类型的文件,那么这种类型的文件才能解析velocity语法】

    2.web页面上可以很方便的调用java后台的方法,不管方法是静态的还是非静态的。只需要在toolbox.xml里面把类配置进去就可以咯。【调用的方法 $class.method()】即可。 

    3.可以使用模版生成静态文档html【特殊情况下才用】

 

 

 

需要下载两个war包,

testng-6.9.9.jar,velocity-1.7.jar【亲测之后发现velocity-1.7.jar会报错,建议用velocity-dep-1.4.jar,因为后者包含了三个war包的内容(commons-collections-3.2.1.jar、commons-lang-2.4.jar和oro-2.0.8.jar)】

百度网盘贡献路径如下:

链接: 密码:2nb7

 

 

 

 

DataBean.java

package main.java.baseReport;import org.testng.ITestNGMethod;import java.util.Collection;import java.util.List;public class DataBean {        private int excludeTestsSize; //未执行的test数量        private int passedTestsSize; //测试通过的数量        private int failedTestsSize; //测试失败的数量        private int skippedTestsSize; //测试跳过的数量        private int allTestsSize; //全部执行的测试的数量        private ITestNGMethod[] allTestsMethod; //全部执行的测试方法        private Collection
excludeTestsMethod; //未执行的测试方法 private String testsTime; //测试耗时 private String passPercent; //测试通过率 private String testName; //测试方法名 private String className; //测试类名 private String duration; //单个测试周期 private String starttime; // private String endtime; // private String params; //测试用参数 private String description; //测试描述 private List
output; //Reporter Output private String dependMethod; //测试依赖方法 private Throwable throwable; //测试异常原因 private StackTraceElement[] stackTrace; // 异常堆栈信息 public int getExcludeTestsSize() { return excludeTestsSize; } public void setExcludeTestsSize(int excludeTestsSize) { this.excludeTestsSize = excludeTestsSize; } public int getPassedTestsSize() { return passedTestsSize; } public void setPassedTestsSize(int passedTestsSize) { this.passedTestsSize = passedTestsSize; } public int getFailedTestsSize() { return failedTestsSize; } public void setFailedTestsSize(int failedTestsSize) { this.failedTestsSize = failedTestsSize; } public int getSkippedTestsSize() { return skippedTestsSize; } public void setSkippedTestsSize(int skippedTestsSize) { this.skippedTestsSize = skippedTestsSize; } public int getAllTestsSize() { return allTestsSize; } public void setAllTestsSize(int allTestsSize) { this.allTestsSize = allTestsSize; } public String getPassPercent() { return passPercent; } public void setPassPercent(String passPercent) { this.passPercent = passPercent; } public String getTestName() { return testName; } public void setTestName(String testName) { this.testName = testName; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getDuration() { return duration; } public String getStarttime() { return starttime; } public void setStarttime(String starttime) { this.starttime = starttime; } public String getEndtime() { return endtime; } public void setEndtime(String endtime) { this.endtime = endtime; } public void setDuration(String duration) { this.duration = duration; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List
getOutput() { return output; } public void setOutput(List
output) { this.output = output; } public String getDependMethod() { return dependMethod; } public void setDependMethod(String dependMethod) { this.dependMethod = dependMethod; } public Throwable getThrowable() { return throwable; } public void setThrowable(Throwable throwable2) { this.throwable = throwable2; } public StackTraceElement[] getStackTrace() { return stackTrace; } public void setStackTrace(StackTraceElement[] stackTrace) { this.stackTrace = stackTrace; } public void setTestsTime(String testsTime) { this.testsTime = testsTime; } public String getTestsTime() { return testsTime; } public void setAllTestsMethod(ITestNGMethod[] allTestsMethod) { this.allTestsMethod = allTestsMethod; } public ITestNGMethod[] getAllTestsMethod() { return allTestsMethod; } public void setExcludeTestsMethod(Collection
excludeTestsMethod) { this.excludeTestsMethod = excludeTestsMethod; } public Collection
getExcludeTestsMethod() { return excludeTestsMethod; } }

  

GenerateReporter
package main.java.baseReport;import org.apache.velocity.Template;import org.apache.velocity.VelocityContext;import org.apache.velocity.app.VelocityEngine;import org.testng.*;import org.testng.xml.XmlSuite;import java.io.*;import java.util.List;import java.util.Map;import java.util.Properties;import static java.lang.System.out;public class GenerateReporter implements IReporter {    @Override    public void generateReport(List
xmlSuites, List
suites, String outputDirectory) { // TODO Auto-generated method stub try { // 初始化并取得Velocity引擎 VelocityEngine ve = new VelocityEngine(); Properties p = new Properties(); //虽然不懂为什么这样设置,但结果是好的.可以用了 p.setProperty("resource.loader", "class"); p.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); ve.init(p); Template t = ve.getTemplate("main/java/baseReport/overview.vm"); VelocityContext context = new VelocityContext(); for (ISuite suite : suites) { Map
suiteResults = suite.getResults(); for (ISuiteResult suiteResult : suiteResults.values()) { ReporterData data = new ReporterData(); ITestContext testContext = suiteResult.getTestContext(); // 把数据填入上下文 context.put("overView", data.testContext(testContext));//测试结果汇总信息 //ITestNGMethod[] allTests = testContext.getAllTestMethods();//所有的测试方法 //Collection
excludeTests = testContext.getExcludedMethods();//未执行的测试方法 IResultMap passedTests = testContext.getPassedTests();//测试通过的测试方法 IResultMap failedTests = testContext.getFailedTests();//测试失败的测试方法 IResultMap skippedTests = testContext.getSkippedTests();//测试跳过的测试方法 //IResultMap starttime=testContext.getStartDate(); //IResultMap endtime=testContext.getEndDate(); context.put("pass", data.testResults(passedTests, ITestResult.SUCCESS)); context.put("fail", data.testResults(failedTests, ITestResult.FAILURE)); context.put("skip", data.testResults(skippedTests, ITestResult.FAILURE)); } } // 输出流 OutputStream out = new FileOutputStream("report.html"); Writer writer = new BufferedWriter(new OutputStreamWriter(out, "utf-8"));//解决乱码问题 // 转换输出 t.merge(context, writer); //System.out.println(writer.toString()); writer.flush(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

 Overview.vm

Test Report

IKEA Web Automatic Test

OverView........
all excluded passed faild skipped StartTime(S) EndTime(S) duration(S) passration alltestMethod excluedMethod
TestResult $overView.allTestsSize $overView.excludeTestsSize $overView.passedTestsSize $overView.failedTestsSize $overView.skippedTestsSize $overView.starttime $overView.endtime $overView.testsTime $overView.passPercent #foreach($p in $overView.allTestsMethod) $p
#end
#foreach($e in $overView.excludeTestsMethod) $e
#end
#foreach( $p in $pass)
#end
PassTests.............
testName className starttime endtime duration params description output dependMethod
$velocityCount ${p.testName} #if(${p.description}) (${p.description}) #end $p.className $p.starttime $p.endtime $p.duration $!p.params $!p.description #foreach($o in $p.output) $o
#end
$p.dependMethod $!p.throwable #if($p.throwable ) #foreach($o in $p.stackTrace) $o
#end #end
#foreach( $p in $fail)
#end
FailedTests...............
testName className StartTime EndTime duration params description output dependMethod throwable stackTrace
$velocityCount $p.testName $p.className $p.starttime $p.endtime $p.duration $!p.params $!p.description #foreach($o in $p.output) $o
#end
$p.dependMethod $p.throwable #if($p.throwable ) #foreach($o in $p.stackTrace) $o
#end #end

  

ReporterData
package main.java.baseReport;import org.testng.*;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.*;public class ReporterData {    // 测试结果Set
转为list,再按执行时间排序 ,返回list public List
sortByTime(Set
str) { List
list = new ArrayList
(); for (ITestResult r : str) { list.add(r); } Collections.sort(list); return list; } public DataBean testContext(ITestContext context) throws ParseException { // 测试结果汇总数据 DataBean data = new DataBean(); ReportUnits units = new ReportUnits(); IResultMap passedTests = context.getPassedTests(); IResultMap failedTests= context.getFailedTests(); IResultMap skipedTests = context.getSkippedTests(); //全部测试周期方法,包括beforetest,beforeclass,beforemethod,aftertest,afterclass,aftermethod //IResultMap passedConfigurations =context.getPassedConfigurations(); //IResultMap failedConfigurations =context.getFailedConfigurations(); //IResultMap skipedConfigurations =context.getSkippedConfigurations(); Collection
excludeTests = context.getExcludedMethods(); int passedTestsSize = passedTests.size(); int failedTestsSize = failedTests.size(); int skipedTestsSize = skipedTests.size(); int excludeTestsSize = excludeTests.size(); //所有测试结果的数量=测试pass+fail+skip的和,因为数据驱动一个测试方法有多次执行的可能,导致方法总数并不等于测试总数 int allTestsSize= passedTestsSize+failedTestsSize+skipedTestsSize; data.setAllTestsSize(allTestsSize); data.setPassedTestsSize(passedTestsSize); data.setFailedTestsSize(failedTestsSize); data.setSkippedTestsSize(skipedTestsSize); data.setExcludeTestsSize(excludeTestsSize); data.setTestsTime(units.getTestDuration(context)); data.setStarttime(units.getStarttime(context)); data.setEndtime(units.getEndTime(context)); data.setPassPercent(units.formatPercentage(passedTestsSize, allTestsSize)); data.setAllTestsMethod(context.getAllTestMethods()); data.setExcludeTestsMethod(context.getExcludedMethods()); return data; } public List
testResults(IResultMap map, int status) { // 测试结果详细数据 List
list = new ArrayList
(); ReportUnits units = new ReportUnits(); map.getAllResults().size(); SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); for (ITestResult result : sortByTime(map.getAllResults())) { DataBean data = new DataBean(); data.setTestName(result.getName()); data.setClassName(result.getTestClass().getName()); data.setDuration(units.formatDuration(result.getEndMillis() - result.getStartMillis())); data.setParams(units.getParams(result)); data.setStarttime(formatter.format(result.getEndMillis())); data.setEndtime(formatter.format(result.getEndMillis())); data.setDescription(result.getMethod().getDescription()); data.setOutput(Reporter.getOutput(result)); data.setDependMethod(units.getDependMethods(result)); data.setThrowable(result.getThrowable()); if (result.getThrowable() != null) { data.setStackTrace(result.getThrowable().getStackTrace()); } list.add(data); } return list; } }

  

ReportUnits
package main.java.baseReport;import java.text.DecimalFormat;import java.text.NumberFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Iterator;import java.util.List;import org.testng.ITestContext;import org.testng.ITestResult;import org.testng.Reporter;public class ReportUnits {    private static final NumberFormat DURATION_FORMAT = new DecimalFormat("#0.000");    private static final NumberFormat PERCENTAGE_FORMAT = new DecimalFormat("#0.00%");    SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");    /**     *测试消耗时长     *return 秒,保留3位小数     */    public String getTestDuration(ITestContext context){        long duration;        duration=context.getEndDate().getTime()-context.getStartDate().getTime();        return formatDuration(duration);    }    public String getStarttime(ITestContext context) throws ParseException {        return formatter.format(context.getStartDate());    }    public String getEndTime(ITestContext context){        return formatter.format(context.getEndDate());        //return context.getStartDate().toString();    }    public String formatDuration(long elapsed)    {        double seconds = (double) elapsed / 1000;        return DURATION_FORMAT.format(seconds);    }    /**     *测试通过率     *return 2.22%,保留2位小数     */    public String formatPercentage(int numerator, int denominator)    {        return PERCENTAGE_FORMAT.format(numerator / (double) denominator);    }    /**     * 获取方法参数,以逗号分隔     * @param result     * @return     */    public String getParams(ITestResult result){        Object[] params = result.getParameters();        List
list = new ArrayList
(params.length); for (Object o:params){ list.add(renderArgument(o)); } return commaSeparate(list); } /** * 获取依赖的方法 * @param result * @return */ public String getDependMethods(ITestResult result){ String[] methods=result.getMethod().getMethodsDependedUpon(); return commaSeparate(Arrays.asList(methods)); } /** * 堆栈轨迹,暂不确定怎么做,放着先 * @param throwable * @return */ public String getCause(Throwable throwable){ StackTraceElement[] stackTrace=throwable.getStackTrace(); //堆栈轨迹 List
list = new ArrayList
(stackTrace.length); for (Object o:stackTrace){ list.add(renderArgument(o)); } return commaSeparate(list); } /** * 获取全部日志输出信息 * @return */ public List
getAllOutput(){ return Reporter.getOutput(); } /** * 按testresult获取日志输出信息 * @param result * @return */ public List
getTestOutput(ITestResult result){ return Reporter.getOutput(result); } /*将object 转换为String*/ private String renderArgument(Object argument) { if (argument == null) { return "null"; } else if (argument instanceof String) { return "\"" + argument + "\""; } else if (argument instanceof Character) { return "\'" + argument + "\'"; } else { return argument.toString(); } } /*将集合转换为以逗号分隔的字符串*/ private String commaSeparate(Collection
strings) { StringBuilder buffer = new StringBuilder(); Iterator
iterator = strings.iterator(); while (iterator.hasNext()) { String string = iterator.next(); buffer.append(string); if (iterator.hasNext()) { buffer.append(", "); } } return buffer.toString(); }}

  

TestResultSort
package main.java.baseReport;import org.testng.ITestResult;public class TestResultSort implements Comparable
{ private Long order; @Override public int compareTo(ITestResult arg0) { // TODO Auto-generated method stub return this.order.compareTo( arg0.getStartMillis());//按test开始时间排序 }}

  

 优缺点比较:

1. 多个测试类一起运行,通过配置testng.xml 一起运行的时候,testNG自带的eport会将多个测试文件显示在同一个报表中,并且根据测试类进行分门别类;自己编写的velocity显示的报表,目前是一个测试类出一个报表,很尴尬。

 只显示了最后一个测试类,并且覆盖了前面的

 

转载于:https://www.cnblogs.com/qianjinyan/p/9437354.html

你可能感兴趣的文章
Zabbix WMI 监控
查看>>
关于for in和for循环的遍历
查看>>
完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三
查看>>
JSP Struts之HTML标签库详解
查看>>
Hp服务器 raid 磁盘故障数据库数据恢复解决方案
查看>>
运维角度浅谈MySQL数据库优化
查看>>
【Spark亚太研究院系-构建Spark集群-配置Hadoop单机模式并运行Wordcount(2)
查看>>
Java通过POI为Excel添加数据验证
查看>>
修改vim的配色方案
查看>>
程矢Axure夜话:程序员眼中的原型设计视频教程之书到用时方恨少
查看>>
网站降权怎么办
查看>>
esxi 4.x升级至5.0
查看>>
Hibernate中save、persist和saveOrUpdate这三个方法的区别
查看>>
c++去掉字符串中连续的空格,只保留一个
查看>>
按钮动画学习2
查看>>
我的友情链接
查看>>
纯靠内链提权重
查看>>
linux因环境变量修改错误,造成命令查找不到,且无法登陆系统解决办法
查看>>
元芳,你怎么看,网络为何会如此流行!
查看>>
计算机运行命令全集
查看>>