接口自动化测试之TestNG测试报告ExtentReports的应用

Posted andrew209

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口自动化测试之TestNG测试报告ExtentReports的应用相关的知识,希望对你有一定的参考价值。

pom.xml导入包

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.TestDemo.www</groupId>
 8     <artifactId>TestDemo</artifactId>
 9     <version>1.0.0</version>
10     <build>
11         <plugins>
12             <plugin>
13                 <groupId>org.apache.maven.plugins</groupId>
14                 <artifactId>maven-compiler-plugin</artifactId>
15                 <configuration>
16                     <source>6</source>
17                     <target>6</target>
18                 </configuration>
19             </plugin>
20         </plugins>
21     </build>
22 
23     <dependencies>
24         <dependency>
25             <groupId>org.testng</groupId>
26             <artifactId>testng</artifactId>
27             <version>6.14.3</version>
28         </dependency>
29         <dependency>
30             <groupId>com.relevantcodes</groupId>
31             <artifactId>extentreports</artifactId>
32             <version>2.41.1</version>
33         </dependency>
34         <dependency>
35             <groupId>com.vimalselvam</groupId>
36             <artifactId>testng-extentsreport</artifactId>
37             <version>1.3.1</version>
38         </dependency>
39         <dependency>
40             <groupId>com.aventstack</groupId>
41             <artifactId>extentreports</artifactId>
42             <version>3.0.6</version>
43         </dependency>
44     </dependencies>
45 
46 </project>

TestNG测试结果监听代码

  1 package com.testng.config;
  2 
  3 import com.aventstack.extentreports.ExtentReports;
  4 import com.aventstack.extentreports.ExtentTest;
  5 import com.aventstack.extentreports.ResourceCDN;
  6 import com.aventstack.extentreports.Status;
  7 import com.aventstack.extentreports.model.TestAttribute;
  8 import com.aventstack.extentreports.reporter.ExtenthtmlReporter;
  9 import com.aventstack.extentreports.reporter.configuration.ChartLocation;
 10 import com.aventstack.extentreports.reporter.configuration.Theme;
 11 import org.testng.*;
 12 import org.testng.xml.XmlSuite;
 13 
 14 import java.io.File;
 15 import java.util.*;
 16 
 17 public class ExtentTestNGIReporterListener implements IReporter {
 18     //生成的路径以及文件名
 19     private static final String OUTPUT_FOLDER = "test-output/";
 20     private static final String FILE_NAME = "index.html";
 21     private ExtentReports extent;
 22 
 23     @Override
 24     public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
 25         init();
 26         boolean createSuiteNode = false;
 27         if(suites.size()>1){
 28             createSuiteNode=true;
 29         }
 30         for (ISuite suite : suites) {
 31             Map<String, ISuiteResult> result = suite.getResults();
 32             //如果suite里面没有任何用例,直接跳过,不在报告里生成
 33             if(result.size()==0){
 34                 continue;
 35             }
 36             //统计suite下的成功、失败、跳过的总用例数
 37             int suiteFailSize=0;
 38             int suitePassSize=0;
 39             int suiteSkipSize=0;
 40             ExtentTest suiteTest=null;
 41             //存在多个suite的情况下,在报告中将同一个suite的测试结果归为一类,创建一级节点。
 42             if(createSuiteNode){
 43                 suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
 44             }
 45             boolean createSuiteResultNode = false;
 46             if(result.size()>1){
 47                 createSuiteResultNode=true;
 48             }
 49             for (ISuiteResult r : result.values()) {
 50                 ExtentTest resultNode;
 51                 ITestContext context = r.getTestContext();
 52                 if(createSuiteResultNode){
 53                     //没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点。
 54                     if( null == suiteTest){
 55                         resultNode = extent.createTest(r.getTestContext().getName());
 56                     }else{
 57                         resultNode = suiteTest.createNode(r.getTestContext().getName());
 58                     }
 59                 }else{
 60                     resultNode = suiteTest;
 61                 }
 62                 if(resultNode != null){
 63                     resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());
 64                     if(resultNode.getModel().hasCategory()){
 65                         resultNode.assignCategory(r.getTestContext().getName());
 66                     }else{
 67                         resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
 68                     }
 69                     resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
 70                     resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
 71                     //统计SuiteResult下的数据
 72                     int passSize = r.getTestContext().getPassedTests().size();
 73                     int failSize = r.getTestContext().getFailedTests().size();
 74                     int skipSize = r.getTestContext().getSkippedTests().size();
 75                     suitePassSize += passSize;
 76                     suiteFailSize += failSize;
 77                     suiteSkipSize += skipSize;
 78                     if(failSize>0){
 79                         resultNode.getModel().setStatus(Status.FAIL);
 80                     }
 81                     resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
 82                 }
 83                 buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
 84                 buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
 85                 buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
 86             }
 87             if(suiteTest!= null){
 88                 suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
 89                 if(suiteFailSize>0){
 90                     suiteTest.getModel().setStatus(Status.FAIL);
 91                 }
 92             }
 93 
 94         }
 95         extent.flush();
 96     }
 97 
 98     private void init() {
 99         //文件夹不存在的话进行创建
100         File reportDir= new File(OUTPUT_FOLDER);
101         if(!reportDir.exists()&& !reportDir .isDirectory()){
102             reportDir.mkdir();
103         }
104         ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
105         // 设置静态文件的DNS
106         //怎么样解决cdn.rawgit.com访问不了的情况
107         htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);
108         htmlReporter.config().setDocumentTitle("自动化测试报告");
109         htmlReporter.config().setReportName("API自动化测试报告");
110         htmlReporter.config().setChartVisibilityOnOpen(true);
111         htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
112         htmlReporter.config().setTheme(Theme.STANDARD);
113         htmlReporter.config().setCSS(".node.level-1  ul{ display:none;} .node.level-1.active ul{display:block;}");
114         extent = new ExtentReports();
115         extent.attachReporter(htmlReporter);
116         extent.setReportUsesManualConfiguration(true);
117     }
118 
119     private void buildTestNodes(ExtentTest extenttest, IResultMap tests, Status status) {
120         //存在父节点时,获取父节点的标签
121         String[] categories=new String[0];
122         if(extenttest != null ){
123             List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();
124             categories = new String[categoryList.size()];
125             for(int index=0;index<categoryList.size();index++){
126                 categories[index] = categoryList.get(index).getName();
127             }
128         }
129 
130         ExtentTest test;
131 
132         if (tests.size() > 0) {
133             //调整用例排序,按时间排序
134             Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {
135                 @Override
136                 public int compare(ITestResult o1, ITestResult o2) {
137                     return o1.getStartMillis()<o2.getStartMillis()?-1:1;
138                 }
139             });
140             treeSet.addAll(tests.getAllResults());
141             for (ITestResult result : treeSet) {
142                 Object[] parameters = result.getParameters();
143                 String name="";
144                 //如果有参数,则使用参数的toString组合代替报告中的name
145                 for(Object param:parameters){
146                     name+=param.toString();
147                 }
148                 if(name.length()>0){
149                     if(name.length()>50){
150                         name= name.substring(0,49)+"...";
151                     }
152                 }else{
153                     name = result.getMethod().getMethodName();
154                 }
155                 if(extenttest==null){
156                     test = extent.createTest(name);
157                 }else{
158                     //作为子节点进行创建时,设置同父节点的标签一致,便于报告检索。
159                     test = extenttest.createNode(name).assignCategory(categories);
160                 }
161                 for (String group : result.getMethod().getGroups())
162                     test.assignCategory(group);
163 
164                 List<String> outputList = Reporter.getOutput(result);
165                 for(String output:outputList){
166                     //将用例的log输出报告中
167                     test.debug(output);
168                 }
169                 if (result.getThrowable() != null) {
170                     test.log(status, result.getThrowable());
171                 }
172                 else {
173                     test.log(status, "Test " + status.toString().toLowerCase() + "ed");
174                 }
175 
176                 test.getModel().setStartTime(getTime(result.getStartMillis()));
177                 test.getModel().setEndTime(getTime(result.getEndMillis()));
178             }
179         }
180     }
181 
182     private Date getTime(long millis) {
183         Calendar calendar = Calendar.getInstance();
184         calendar.setTimeInMillis(millis);
185         return calendar.getTime();
186     }
187 }

运行上一节文章的testng.xml, 会输出一个测试报告, 在浏览器中打开输出的测试报告index.html

技术分享图片

 

以上是关于接口自动化测试之TestNG测试报告ExtentReports的应用的主要内容,如果未能解决你的问题,请参考以下文章

APP接口自动化测试JAVA+TestNG之HTTP接口测试实例

APP接口自动化测试JAVA+TestNG之HTTP接口测试实例

APP接口自动化测试JAVA+TestNG之HTTP接口测试实例

APP接口自动化测试JAVA+TestNG之HTTP接口测试实例

接口自动化测试之TestNG学习

走进Java接口测试之测试框架TestNG数据驱动(入门篇)