之前用testNG自带的test-outputemailable-report.html,做出的UI自动化测试报告,页面不太好看。
在网上找到一个新的报告编写,自己尝试了一下,买了一些坑,出的结果比以前稍好。
需要下载两个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)】
百度网盘贡献路径如下:
链接:https://pan.baidu.com/s/1FeN-di2T_nMo3ahHQ91xtg 密码:2nb7
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<ITestNGMethod> excludeTestsMethod; //未执行的测试方法 ???????private String testsTime; //测试耗时 ???????private String passPercent; //测试通过率 ???????private String testName; //测试方法名 ???????private String className; //测试类名 ???????private String duration; //单个测试周期 ???????private String params; //测试用参数 ???????private String description; //测试描述 ???????private List<String> 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 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<String> getOutput() { ???????????return output; ???????} ???????public void setOutput(List<String> 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<ITestNGMethod> excludeTestsMethod) { ???????????this.excludeTestsMethod = excludeTestsMethod; ???????} ???????public Collection<ITestNGMethod> getExcludeTestsMethod() { ???????????return excludeTestsMethod; ???????} ???}
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<XmlSuite> xmlSuites, List<ISuite> 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"); ???????????//.\Tools\IEDriverServer.exe ???????????VelocityContext context = new VelocityContext(); ???????????for (ISuite suite : suites) { ???????????????Map<String, ISuiteResult> 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<ITestNGMethod> excludeTests = testContext.getExcludedMethods();//未执行的测试方法 ???????????????????IResultMap passedTests = testContext.getPassedTests();//测试通过的测试方法 ???????????????????IResultMap failedTests = testContext.getFailedTests();//测试失败的测试方法 ???????????????????IResultMap skippedTests = testContext.getSkippedTests();//测试跳过的测试方法 ???????????????????context.put("pass", data.testResults(passedTests, ITestResult.SUCCESS)); ???????????????????context.put("fail", data.testResults(failedTests, ITestResult.FAILURE)); ???????????????????context.put("skip", data.testResults(skippedTests, ITestResult.FAILURE)); ???????????????} ???????????} ???????????// 输出流 ???????????//<span style = "white-space:pre" ></span > ???????????// Writer writer = new BufferedWriter(new FileWriter("report.html")); ???????????//<span style = "white-space:pre" ></span > ???????????????????OutputStream out = new FileOutputStream("report.html"); ???????????//<span style = "white-space:pre" ></span > ???????????????????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(); ???????} ???} ???}
<?xml version="1.0" encoding="utf-8" ?><head> ???<title>Test Report</title> ???<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> ???<meta name="description" content="TestNG unit test results." /></head><body><h1>IKEA Web Automatic Test</h1><table border="1"> ???<tr> ???????<th>OverView........</th> ???????<th colspan="6" > ???????????<div > ???????????????<a href="http://www.baidu.com">Detail Information for test cases</a> ???????????</div> ???????</th> ???</tr> ???<tr > ???????<td> </td> ???????<th>all</th> ???????<th>excluded</th> ???????<th>passed</th> ???????<th>faild</th> ???????<th>skipped</th> ???????<th>duration(S)</th> ???????<th>passration</th> ???????<th>alltestMethod</th> ???????<th>excluedMethod</th> ???</tr> ???<tr> ???????<td>TestResult</td> ???????<td>$overView.allTestsSize</td> ???????<td>$overView.excludeTestsSize</td> ???????<td>$overView.passedTestsSize</td> ???????<td>$overView.failedTestsSize</td> ???????<td>$overView.skippedTestsSize</td> ???????<td>$overView.testsTime</td> ???????<td>$overView.passPercent</td> ???????<td> ???????????#foreach($p in $overView.allTestsMethod) ???????????????$p<br/> ???????????#end ???????</td> ???????<td> ???????????#foreach($e in $overView.excludeTestsMethod) ???????????????$e<br/> ???????????#end ???????</td> ???</tr></table><br/><br/><table border="1"> ???<tr> ???????<th>PassTests.............</th> ???????<th colspan="6" > ???????????<div > ???????????????<a href="http://www.baidu.com">Detail Information for test cases</a> ???????????</div> ???????</th> ???</tr> ???<tr > ???????<td> </td> ???????<th>testName</th> ???????<th>className</th> ???????<th>duration</th> ???????<th>params</th> ???????<th>description</th> ???????<th>output</th> ???????<th>dependMethod</th> ???</tr> ???#foreach( $p in $pass) ???<tr> ???????<td>$velocityCount</td> ???????<td>${p.testName} ???????????#if(${p.description}) ???????????????(${p.description}) ???????????#end</td> ???????<td>$p.className</td> ???????<td>$p.duration</td> ???????<td>$!p.params</td> ???????<td>$!p.description</td> ???????<td> ???????????#foreach($o in $p.output) ???????????????$o<br/> ???????????#end ???????</td> ???????<td>$p.dependMethod</td> ???????<td>$!p.throwable</td> ???????<td> ???????????#if($p.throwable ) ???????????????#foreach($o in $p.stackTrace) ???????????????????$o<br/> ???????????????#end ???????????#end ???????</td> ???#end</tr></table><br/><br/><br/><table border="1"> ???<tr> ???????<th>FailedTests...............</th> ???????<th colspan="6" > ???????????<div > ???????????????<a href="http://www.baidu.com">Detail Information for test cases</a> ???????????</div> ???????</th> ???</tr> ???<tr > ???????<td> </td> ???????<th>testName</th> ???????<th>className</th> ???????<th>duration</th> ???????<th>params</th> ???????<th>description</th> ???????<th>output</th> ???????<th>dependMethod</th> ???????<th>throwable</th> ???????<th>stackTrace</th> ???</tr> ???#foreach( $p in $fail) ???<tr> ???????<td>$velocityCount</td> ???????<td>$p.testName</td> ???????<td>$p.className</td> ???????<td>$p.duration</td> ???????<td>$!p.params</td> ???????<td>$!p.description</td> ???????<td> ???????????#foreach($o in $p.output) ???????????????$o<br/> ???????????#end ???????</td> ???????<td>$p.dependMethod</td> ???????<td>$p.throwable</td> ???????<td> ???????????#if($p.throwable ) ???????????????#foreach($o in $p.stackTrace) ???????????????????$o<br/> ???????????????#end ???????????#end ???????</td> ???#end</tr></table><br/><br/></body>
package main.java.baseReport;import org.testng.*;import java.util.*;public class ReporterData { ???// 测试结果Set<ITestResult>转为list,再按执行时间排序 ,返回list ???public List<ITestResult> sortByTime(Set<ITestResult> str) { ???????List<ITestResult> list = new ArrayList<ITestResult>(); ???????for (ITestResult r : str) { ???????????list.add(r); ???????} ???????Collections.sort(list); ???????return list; ???} ???public DataBean testContext(ITestContext context) { ???????// 测试结果汇总数据 ???????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<ITestNGMethod> 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.setPassPercent(units.formatPercentage(passedTestsSize, allTestsSize)); ???????data.setAllTestsMethod(context.getAllTestMethods()); ???????data.setExcludeTestsMethod(context.getExcludedMethods()); ???????return data; ???} ???public List<DataBean> testResults(IResultMap map, int status) { ???????// 测试结果详细数据 ???????List<DataBean> list = new ArrayList<DataBean>(); ???????ReportUnits units = new ReportUnits(); ???????map.getAllResults().size(); ???????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.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; ???} ???}
package main.java.baseReport;import java.text.DecimalFormat;import java.text.NumberFormat;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%"); ???/** ????*测试消耗时长 ????*return 秒,保留3位小数 ????*/ ???public String getTestDuration(ITestContext context){ ???????long duration; ???????duration=context.getEndDate().getTime()-context.getStartDate().getTime(); ???????return formatDuration(duration); ???} ???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<String> list = new ArrayList<String>(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<String> list = new ArrayList<String>(stackTrace.length); ???????for (Object o:stackTrace){ ???????????list.add(renderArgument(o)); ???????} ???????return ?commaSeparate(list); ???} ???/** ????* 获取全部日志输出信息 ????* @return ????*/ ???public List<String> getAllOutput(){ ???????return Reporter.getOutput(); ???} ???/** ????* 按testresult获取日志输出信息 ????* @param result ????* @return ????*/ ???public List<String> 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<String> strings) ???{ ???????StringBuilder buffer = new StringBuilder(); ???????Iterator<String> iterator = strings.iterator(); ???????while (iterator.hasNext()) ???????{ ???????????String string = iterator.next(); ???????????buffer.append(string); ???????????if (iterator.hasNext()) ???????????{ ???????????????buffer.append(", "); ???????????} ???????} ???????return buffer.toString(); ???}}
package main.java.baseReport;import org.testng.ITestResult;public class TestResultSort implements Comparable<ITestResult> { ???private Long order; ???@Override ???public int compareTo(ITestResult arg0) { ???????// TODO Auto-generated method stub ???????return this.order.compareTo( arg0.getStartMillis());//按test开始时间排序 ???}}
testNG 编写自定义html报告
原文地址:https://www.cnblogs.com/qianjinyan/p/9437354.html