java测试报告html_testng生成自定义html报告

转自:https://blog.csdn.net/kdslkd/article/details/51198433

testng原生的或reportng的报告总有些不符合需要,尝试生成自定义测试报告,

用到的依赖包:testng-6.9.9.jar,velocity-1.7.jar

1.定义一个DataBean,保存需要收集的数据

只定义部分数据,比如suite、testname、groups等好多数据还没,需要用到的时候再加了

1 packagecom.reporter.main;2

3 importjava.util.Collection;4 importjava.util.List;5

6 importorg.testng.ITestNGMethod;7

8 public classDataBean {9 private int excludeTestsSize; //未执行的test数量

10 private int passedTestsSize; //测试通过的数量

11 private int failedTestsSize; //测试失败的数量

12 private int skippedTestsSize; //测试跳过的数量

13 private int allTestsSize; //全部执行的测试的数量

14 private ITestNGMethod[] allTestsMethod; //全部执行的测试方法

15 private Collection excludeTestsMethod; //未执行的测试方法

16 private String testsTime; //测试耗时

17 private String passPercent; //测试通过率

18 private String testName; //测试方法名

19 private String className; //测试类名

20 private String duration; //单个测试周期

21 private String params; //测试用参数

22 private String description; //测试描述

23 private List output; //Reporter Output

24 private String dependMethod; //测试依赖方法

25 private Throwable throwable; //测试异常原因

26 private StackTraceElement[] stackTrace; //异常堆栈信息

27

28 public intgetExcludeTestsSize() {29 returnexcludeTestsSize;30 }31

32 public void setExcludeTestsSize(intexcludeTestsSize) {33 this.excludeTestsSize =excludeTestsSize;34 }35

36 public intgetPassedTestsSize() {37 returnpassedTestsSize;38 }39

40 public void setPassedTestsSize(intpassedTestsSize) {41 this.passedTestsSize =passedTestsSize;42 }43

44 public intgetFailedTestsSize() {45 returnfailedTestsSize;46 }47

48 public void setFailedTestsSize(intfailedTestsSize) {49 this.failedTestsSize =failedTestsSize;50 }51

52 public intgetSkippedTestsSize() {53 returnskippedTestsSize;54 }55

56 public void setSkippedTestsSize(intskippedTestsSize) {57 this.skippedTestsSize =skippedTestsSize;58 }59

60 public intgetAllTestsSize() {61 returnallTestsSize;62 }63

64 public void setAllTestsSize(intallTestsSize) {65 this.allTestsSize =allTestsSize;66 }67

68 publicString getPassPercent() {69 returnpassPercent;70 }71

72 public voidsetPassPercent(String passPercent) {73 this.passPercent =passPercent;74 }75

76 publicString getTestName() {77 returntestName;78 }79

80 public voidsetTestName(String testName) {81 this.testName =testName;82 }83

84 publicString getClassName() {85 returnclassName;86 }87

88 public voidsetClassName(String className) {89 this.className =className;90 }91

92 publicString getDuration() {93 returnduration;94 }95

96 public voidsetDuration(String duration) {97 this.duration =duration;98 }99

100 publicString getParams() {101 returnparams;102 }103

104 public voidsetParams(String params) {105 this.params =params;106 }107

108 publicString getDescription() {109 returndescription;110 }111

112 public voidsetDescription(String description) {113 this.description =description;114 }115

116 public ListgetOutput() {117 returnoutput;118 }119

120 public void setOutput(Listoutput) {121 this.output =output;122 }123

124 publicString getDependMethod() {125 returndependMethod;126 }127

128 public voidsetDependMethod(String dependMethod) {129 this.dependMethod =dependMethod;130 }131

132 publicThrowable getThrowable() {133 returnthrowable;134 }135

136 public voidsetThrowable(Throwable throwable2) {137 this.throwable =throwable2;138 }139

140 publicStackTraceElement[] getStackTrace() {141 returnstackTrace;142 }143

144 public voidsetStackTrace(StackTraceElement[] stackTrace) {145 this.stackTrace =stackTrace;146 }147

148 public voidsetTestsTime(String testsTime) {149 this.testsTime =testsTime;150 }151

152 publicString getTestsTime() {153 returntestsTime;154 }155

156 public voidsetAllTestsMethod(ITestNGMethod[] allTestsMethod) {157 this.allTestsMethod =allTestsMethod;158 }159

160 publicITestNGMethod[] getAllTestsMethod() {161 returnallTestsMethod;162 }163

164 public void setExcludeTestsMethod(CollectionexcludeTestsMethod) {165 this.excludeTestsMethod =excludeTestsMethod;166 }167

168 public CollectiongetExcludeTestsMethod() {169 returnexcludeTestsMethod;170 }171

172 }

2.对需要特别处理的报告元素,比如测试周期、通过率

1 packagecom.reporter.main;2

3 importjava.text.DecimalFormat;4 importjava.text.NumberFormat;5 importjava.util.ArrayList;6 importjava.util.Arrays;7 importjava.util.Collection;8 importjava.util.Iterator;9 importjava.util.List;10 importorg.testng.ITestContext;11 importorg.testng.ITestResult;12 importorg.testng.Reporter;13

14 public classReportUnits {15 private static final NumberFormat DURATION_FORMAT = new DecimalFormat("#0.000");16 private static final NumberFormat PERCENTAGE_FORMAT = new DecimalFormat("#0.00%");17 /**

18 *测试消耗时长19 *return 秒,保留3位小数20 */

21 publicString getTestDuration(ITestContext context){22 longduration;23 duration=context.getEndDate().getTime()-context.getStartDate().getTime();24 returnformatDuration(duration);25 }26

27 public String formatDuration(longelapsed)28 {29 double seconds = (double) elapsed / 1000;30 returnDURATION_FORMAT.format(seconds);31 }32 /**

33 *测试通过率34 *return 2.22%,保留2位小数35 */

36 public String formatPercentage(int numerator, intdenominator)37 {38 return PERCENTAGE_FORMAT.format(numerator / (double) denominator);39 }40

41 /**

42 * 获取方法参数,以逗号分隔43 *@paramresult44 *@return

45 */

46 publicString getParams(ITestResult result){47 Object[] params =result.getParameters();48 List list = new ArrayList(params.length);49 for(Object o:params){50 list.add(renderArgument(o));51 }52 returncommaSeparate(list);53 }54 /**

55 * 获取依赖的方法56 *@paramresult57 *@return

58 */

59 publicString getDependMethods(ITestResult result){60 String[] methods=result.getMethod().getMethodsDependedUpon();61 returncommaSeparate(Arrays.asList(methods));62 }63 /**

64 * 堆栈轨迹,暂不确定怎么做,放着先65 *@paramthrowable66 *@return

67 */

68 publicString getCause(Throwable throwable){69 StackTraceElement[] stackTrace=throwable.getStackTrace(); //堆栈轨迹

70 List list = new ArrayList(stackTrace.length);71 for(Object o:stackTrace){72 list.add(renderArgument(o));73 }74 returncommaSeparate(list);75 }76 /**

77 * 获取全部日志输出信息78 *@return

79 */

80 public ListgetAllOutput(){81 returnReporter.getOutput();82 }83

84 /**

85 * 按testresult获取日志输出信息86 *@paramresult87 *@return

88 */

89 public ListgetTestOutput(ITestResult result){90 returnReporter.getOutput(result);91 }92

93

94 /*将object 转换为String*/

95 privateString renderArgument(Object argument)96 {97 if (argument == null)98 {99 return "null";100 }101 else if (argument instanceofString)102 {103 return "\"" + argument + "\"";104 }105 else if (argument instanceofCharacter)106 {107 return "\'" + argument + "\'";108 }109 else

110 {111 returnargument.toString();112 }113 }114 /*将集合转换为以逗号分隔的字符串*/

115 private String commaSeparate(Collectionstrings)116 {117 StringBuilder buffer = newStringBuilder();118 Iterator iterator =strings.iterator();119 while(iterator.hasNext())120 {121 String string =iterator.next();122 buffer.append(string);123 if(iterator.hasNext())124 {125 buffer.append(", ");126 }127 }128 returnbuffer.toString();129 }130 }

3.测试方法排序,按测试方法执行时间排序

遍历 suites 得到的getAllResults()是一个set 集合,需要对数据进行排序

这里是将getAllResults()转为list,实现Comparable接口的方法进行排序的.

(好像是可以将getAllResults()转成TreeSet排序?)

1 packagecom.reporter.main;2

3 importorg.testng.ITestResult;4

5 public class TestResultSort implements Comparable{6 privateLong order;7 @Override8 public intcompareTo(ITestResult arg0) {9 //TODO Auto-generated method stub

10 return this.order.compareTo( arg0.getStartMillis());//按test开始时间排序

11 }12

13 }

4.得到测试报告数据

1 packageorg.reporter.main;2

3

4 importjava.util.ArrayList;5 importjava.util.Collection;6 importjava.util.Collections;7 importjava.util.List;8 importjava.util.Set;9

10

11 importorg.testng.IResultMap;12 importorg.testng.ITestContext;13 importorg.testng.ITestNGMethod;14 importorg.testng.ITestResult;15 importorg.testng.Reporter;16

17

18

19

20 public classReporterData {21 //测试结果Set转为list,再按执行时间排序 ,返回list

22 public List sortByTime(Setstr) {23 List list = new ArrayList();24 for(ITestResult r : str) {25 list.add(r);26 }27 Collections.sort(list);28 returnlist;29

30

31 }32

33 publicDataBean testContext(ITestContext context) {34 //测试结果汇总数据

35 DataBean data = newDataBean();36 ReportUnits units = newReportUnits();37 IResultMap passedTests =context.getPassedTests();38 IResultMap failedTests=context.getFailedTests();39 IResultMap skipedTests =context.getSkippedTests();40 //全部测试周期方法,包括beforetest,beforeclass,beforemethod,aftertest,afterclass,aftermethod41 //IResultMap passedConfigurations =context.getPassedConfigurations();42 //IResultMap failedConfigurations =context.getFailedConfigurations();43 //IResultMap skipedConfigurations =context.getSkippedConfigurations();

44 Collection excludeTests =context.getExcludedMethods();45

46 int passedTestsSize =passedTests.size();47 int failedTestsSize =failedTests.size();48 int skipedTestsSize =skipedTests.size();49 int excludeTestsSize =excludeTests.size();50 //所有测试结果的数量=测试pass+fail+skip的和,因为数据驱动一个测试方法有多次执行的可能,导致方法总数并不等于测试总数

51 int allTestsSize= passedTestsSize+failedTestsSize+skipedTestsSize;52 data.setAllTestsSize(allTestsSize);53 data.setPassedTestsSize(passedTestsSize);54 data.setFailedTestsSize(failedTestsSize);55 data.setSkippedTestsSize(skipedTestsSize);56 data.setExcludeTestsSize(excludeTestsSize);57 data.setTestsTime(units.getTestDuration(context));58 data.setPassPercent(units.formatPercentage(passedTestsSize, allTestsSize));59 data.setAllTestsMethod(context.getAllTestMethods());60 data.setExcludeTestsMethod(context.getExcludedMethods());61

62 returndata;63

64

65 }66

67

68 public List testResults(IResultMap map, intstatus) {69 //测试结果详细数据

70 List list = new ArrayList();71 ReportUnits units = newReportUnits();72 map.getAllResults().size();73 for(ITestResult result : sortByTime(map.getAllResults())) {74 DataBean data = newDataBean();75 data.setTestName(result.getName());76 data.setClassName(result.getTestClass().getName());77 data.setDuration(units.formatDuration(result.getEndMillis()78 -result.getStartMillis()));79 data.setParams(units.getParams(result));80 data.setDescription(result.getMethod().getDescription());81 data.setOutput(Reporter.getOutput(result));82 data.setDependMethod(units.getDependMethods(result));83 data.setThrowable(result.getThrowable());84 if (result.getThrowable() != null) {85 data.setStackTrace(result.getThrowable().getStackTrace());86 }87 list.add(data);88 }89 returnlist;90 }91

92 }

5.生成测试报告,生成的测试报告是项目根目录下的report.html(要定制的话再改了)

使用 IReporter 监听器。IReporter 监听器只有一个方法需要实现。

void generateReport(java.util.List xmlSuites, java.util.List

suites, java.lang.String outputDirectory)

该方法在所有测试方法执行结束后被调用,通过遍历 xmlSuites 和 suites 能够获取所有测试方法的信息以及测试结果。outputDirectory 是默认的测试报表生成路径,当然你可以指定其他路径生成报表。

1 packagecom.reporter.main;2

3 importjava.io.BufferedWriter;4 importjava.io.FileWriter;5 importjava.io.Writer;6 importjava.util.List;7 importjava.util.Map;8 importjava.util.Properties;9 importorg.apache.velocity.Template;10 importorg.apache.velocity.VelocityContext;11 importorg.apache.velocity.app.VelocityEngine;12 importorg.testng.IReporter;13 importorg.testng.IResultMap;14 importorg.testng.ISuite;15 importorg.testng.ISuiteResult;16 importorg.testng.ITestContext;17 importorg.testng.ITestResult;18 importorg.testng.xml.XmlSuite;19

20 public class GenerateReporter implementsIReporter {21 @Override22 public void generateReport(List xmlSuites, Listsuites,23 String outputDirectory) {24 //TODO Auto-generated method stub

25 try{26 //初始化并取得Velocity引擎

27 VelocityEngine ve = newVelocityEngine();28 Properties p = newProperties();29 //虽然不懂为什么这样设置,但结果是好的.可以用了

30 p.setProperty("resource.loader", "class");31 p.setProperty("class.resource.loader.class","org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");32 ve.init(p);33 Template t = ve.getTemplate("com/reporter/VMmodel/overview.vm");34 VelocityContext context = newVelocityContext();35

36 for(ISuite suite : suites) {37 Map suiteResults =suite.getResults();38 for(ISuiteResult suiteResult : suiteResults.values()) {39 ReporterData data = newReporterData();40 ITestContext testContext =suiteResult.getTestContext();41 //把数据填入上下文

42 context.put("overView", data.testContext(testContext));//测试结果汇总信息43 //ITestNGMethod[] allTests = testContext.getAllTestMethods();//所有的测试方法44 //Collection excludeTests = testContext.getExcludedMethods();//未执行的测试方法

45 IResultMap passedTests = testContext.getPassedTests();//测试通过的测试方法

46 IResultMap failedTests = testContext.getFailedTests();//测试失败的测试方法

47 IResultMap skippedTests = testContext.getSkippedTests();//测试跳过的测试方法

48

49 context.put("pass", data.testResults(passedTests, ITestResult.SUCCESS));50 context.put("fail", data.testResults(failedTests, ITestResult.FAILURE));51 context.put("skip", data.testResults(skippedTests, ITestResult.FAILURE));52

53

54

55 }56 }57 //输出流

58 //Writer writer = new BufferedWriter(new FileWriter("report.html"));

59 OutputStream out=new FileOutputStream("report.html");60 Writer writer = new BufferedWriter(new OutputStreamWriter(out,"utf-8"));//解决乱码问题61 //转换输出

62 t.merge(context, writer);63 //System.out.println(writer.toString());

64 writer.flush();65 } catch(Exception e) {66 //TODO Auto-generated catch block

67 e.printStackTrace();68 }69 }70

71

72 }

6.测试报告模板,文件后辍为vm,比如overview.vm,内容差不多就是一个html文件,(要漂亮报告找前端。。。)

1 <?xml version="1.0" encoding="utf-8"?>

2

3

4

test

5

6

7

8

9

10

11

Test

12

13

14

OverView........

15

16

17 aaa

18

19

20

21

22

 

23

all

24

excluded

25

passed

26

faild

27

skipped

28

duration(S)

29

passration

30

alltestMethod

31

excluedMethod

32

33

34

35

TestResult

36

$overView.allTestsSize

37

$overView.excludeTestsSize

38

$overView.passedTestsSize

39

$overView.failedTestsSize

40

$overView.skippedTestsSize

41

$overView.testsTime

42

$overView.passPercent

43

44 #foreach($p in $overView.allTestsMethod)45 $p

46 #end47

48

49 #foreach($e in $overView.excludeTestsMethod)50 $e

51 #end52

53

54

55

56

57

58

PassTests.............

59

60

61 aaa

62

63

64

65

66

 

67

testName

68

className

69

duration

70

params

71

description

72

output

73

dependMethod

74

75

76 #foreach( $p in $pass)77

78

$velocityCount

79

${p.testName}80 #if(${p.description})81 (${p.description})82 #end

83

$p.className

84

$p.duration

85

$!p.params

86

$!p.description

87

88 #foreach($o in $p.output)89 $o

90 #end91

92

$p.dependMethod

93

$!p.throwable

94

95 #if($p.throwable )96 #foreach($o in $p.stackTrace)97 $o

98 #end99 #end100

101 #end102

103

104

105

106

107

108

109

110

111

112

FailedTests...............

113

114

115 aaa

116

117

118

119

120

 

121

testName

122

className

123

duration

124

params

125

description

126

output

127

dependMethod

128

throwable

129

stackTrace

130

131

132 #foreach( $p in $fail)133

134

$velocityCount

135

$p.testName

136

$p.className

137

$p.duration

138

$!p.params

139

$!p.description

140

141 #foreach($o in $p.output)142 $o

143 #end144

145

$p.dependMethod

146

$p.throwable

147

148 #if($p.throwable )149 #foreach($o in $p.stackTrace)150 $o

151 #end152 #end153

154 #end155

156

157

158

159

160

161

162

163

164

165

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值