zoukankan      html  css  js  c++  java
  • 使用ExtentReport生成漂亮的测试报告

    1.引入依赖

     1         <dependency>
     2             <groupId>com.relevantcodes</groupId>
     3             <artifactId>extentreports</artifactId>
     4             <version>2.41.1</version>
     5         </dependency>
     6 
     7         <dependency>
     8             <groupId>com.vimalselvam</groupId>
     9             <artifactId>testng-extentsreport</artifactId>
    10             <version>1.3.1</version>
    11         </dependency>
    12 
    13         <dependency>
    14             <groupId>com.aventstack</groupId>
    15             <artifactId>extentreports</artifactId>
    16             <version>3.0.6</version>
    17         </dependency>    

    2.编写测试

     1 public class Demo1 {
     2     @Test
     3     public void test1() {
     4         Assert.assertEquals("aaa", "aaa");
     5     }
     6     @Test
     7     public void test2() {
     8         Assert.assertEquals(1, 2);
     9     }
    10     
    11     @Test
    12     public void test3() {
    13         Reporter.log("这是我们自己写的日志");
    14         throw new RuntimeException("这是我们自己的运行时异常");
    15     }
    16 }

    3.testng.xml配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <suite name="我们自己的接口测试套件">
     3     <test name="这些是测试模块">
     4         <classes>
     5             <class name="com.test.testng.Demo1">
     6                 <method>
     7                     <include name="test1"/>
     8                     <include name="test2"/>
     9                     <include name="test3"/>
    10                 </method>
    11             </class>
    12         </classes>
    13     </test>
    14     <listeners>
    15         <listener class-name="com.vimalselvam.testng.listener.ExtentTestNgFormatter"/>
    16     </listeners>
    17 </suite>

    4.解决css无法加载

    4.1新建ExtentTestNGIReporterListener实现IReporter,设置静态文件的DNS

      1 import com.aventstack.extentreports.ExtentReports;
      2 import com.aventstack.extentreports.ExtentTest;
      3 import com.aventstack.extentreports.ResourceCDN;
      4 import com.aventstack.extentreports.Status;
      5 import com.aventstack.extentreports.model.TestAttribute;
      6 import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
      7 import com.aventstack.extentreports.reporter.configuration.ChartLocation;
      8 import com.aventstack.extentreports.reporter.configuration.Theme;
      9 import org.testng.*;
     10 import org.testng.xml.XmlSuite;
     11 
     12 import java.io.File;
     13 import java.util.*;
     14 
     15 public class ExtentTestNGIReporterListener implements IReporter {
     16     //生成的路径以及文件名
     17     private static final String OUTPUT_FOLDER = "test-output/";
     18     private static final String FILE_NAME = "index.html";
     19 
     20     private ExtentReports extent;
     21 
     22     @Override
     23     public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
     24         init();
     25         boolean createSuiteNode = false;
     26         if(suites.size()>1){
     27             createSuiteNode=true;
     28         }
     29         for (ISuite suite : suites) {
     30             Map<String, ISuiteResult> result = suite.getResults();
     31             //如果suite里面没有任何用例,直接跳过,不在报告里生成
     32             if(result.size()==0){
     33                 continue;
     34             }
     35             //统计suite下的成功、失败、跳过的总用例数
     36             int suiteFailSize=0;
     37             int suitePassSize=0;
     38             int suiteSkipSize=0;
     39             ExtentTest suiteTest=null;
     40             //存在多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。
     41             if(createSuiteNode){
     42                 suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
     43             }
     44             boolean createSuiteResultNode = false;
     45             if(result.size()>1){
     46                 createSuiteResultNode=true;
     47             }
     48             for (ISuiteResult r : result.values()) {
     49                 ExtentTest resultNode;
     50                 ITestContext context = r.getTestContext();
     51                 if(createSuiteResultNode){
     52                     //没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点。
     53                     if( null == suiteTest){
     54                         resultNode = extent.createTest(r.getTestContext().getName());
     55                     }else{
     56                         resultNode = suiteTest.createNode(r.getTestContext().getName());
     57                     }
     58                 }else{
     59                     resultNode = suiteTest;
     60                 }
     61                 if(resultNode != null){
     62                     resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());
     63                     if(resultNode.getModel().hasCategory()){
     64                         resultNode.assignCategory(r.getTestContext().getName());
     65                     }else{
     66                         resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
     67                     }
     68                     resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
     69                     resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
     70                     //统计SuiteResult下的数据
     71                     int passSize = r.getTestContext().getPassedTests().size();
     72                     int failSize = r.getTestContext().getFailedTests().size();
     73                     int skipSize = r.getTestContext().getSkippedTests().size();
     74                     suitePassSize += passSize;
     75                     suiteFailSize += failSize;
     76                     suiteSkipSize += skipSize;
     77                     if(failSize>0){
     78                         resultNode.getModel().setStatus(Status.FAIL);
     79                     }
     80                     resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
     81                 }
     82                 buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
     83                 buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
     84                 buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
     85             }
     86             if(suiteTest!= null){
     87                 suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
     88                 if(suiteFailSize>0){
     89                     suiteTest.getModel().setStatus(Status.FAIL);
     90                 }
     91             }
     92 
     93         }
     94         extent.flush();
     95     }
     96 
     97     private void init() {
     98         //文件夹不存在的话进行创建
     99         File reportDir= new File(OUTPUT_FOLDER);
    100         if(!reportDir.exists()&& !reportDir .isDirectory()){
    101             reportDir.mkdir();
    102         }
    103         ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
    104         // 设置静态文件的DNS
    105         //怎么样解决cdn.rawgit.com访问不了的情况
    106         htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);
    107 
    108         htmlReporter.config().setDocumentTitle("api自动化测试报告");
    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 }

    5.修改testng.ml监听器设置

    <listeners>
            <listener class-name="com.test.testng.ExtentTestNGIReporterListener"></listener>
        </listeners>

    6.再次运行testng.xml,生成报告后,test-output/index.html,得到正常css样式的报告

  • 相关阅读:
    装箱与拆箱
    java中final的用法
    一次坑爹的Oracle in查询
    Spring-Security-Oauth整合Spring-Security,拦截器
    jvisualvm连接远程Tomcat
    7.Spring-Cloud服务容错保护之Hystrix初探
    8.Spring-Cloud-Hystrix之异常处理
    9.Spring-Cloud-Hystrix之请求缓存(踩坑)
    10.Spring-Cloud-Hystrix之熔断监控Hystrix Dashboard单个应用
    11.Spring-Cloud-Hystrix之熔断监控Turbine
  • 原文地址:https://www.cnblogs.com/heyuling/p/12069235.html
Copyright © 2011-2022 走看看