1.2 testNG生成报告

457 阅读4分钟

1、idea中生成testNG的单元测试报告:

1.1)下载maven

获得文件:apache-maven-3.8.2-bin.zip

1.1.1)maven配置阿里仓库

在conf/setting.xml中的mirrors下添加mirror子节点

1.1.2)在maven目录下新建本地仓库repository:

将引用包下载到本地仓库\maven\repository

1.2)新建maven项目:untitled_one

1.2.1)idea中配置maven:

File—Settings—Bulid—Bulid Tools—Maven
Maven home path:选择maven解压的路径,如:D:/maven/apache-maven-3.8.2
User settings file:选择配置的Maven仓库,如:D:\maven\apache-maven-3.8.2\conf\settings.xml
Local repository:选择Maven配置的本地仓库,如:D:\maven\repository

1.2.2)maven仓库导入项目:

File—Project Structure—Modules—Dependencies—"+"
         —选择(D:\maven\apache-maven-3.8.2与D:\maven\repository)—Apply—OK

1.3)项目的pom.xml文件加入:

1.3.1)

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>com.relevantcodes</groupId>
         <artifactId>extentreports</artifactId>
         <version>2.41.1</version>
      </dependency>
      <dependency>
         <groupId>com.vimalselvam</groupId>
         <artifactId>testng-extentsreport</artifactId>
         <version>1.3.1</version>
      </dependency>
      <dependency>
         <groupId>com.aventstack</groupId>
         <artifactId>extentreports</artifactId>
         <version>3.0.6</version>
      </dependency>
   </dependencies>
</dependencyManagement>

1.3.2)加载pom.xml文件,右键pom.xml文件—Maven—Reload project

1.4)src/java/中新建Package:com.test.test_one

1.5)com.test.test_one包下新建类:Unit_Test_Report

1.6)Test_Ones实现IReporter接口

1.6.1)Unit_Test_Report implements IReporter

1.6.2)选中IReporter(Alt+Enter)点击add maven dependency(import org.testng.IReporter;)

1.6.3)实现报告的路径:

public class Unit_Test_Report implements IReporter {
     /* 生成报告路径与文件名 */
     private static final String OUTPUT_FOLDER = "test-output/";
     private static final String FILE_NAME = "test-output/";
     /* 生成报告情况 */
     private ExtentReports extent;
}

1.6.4)Test_Ones编写init、getTimebuildTestNodes方法,重写generateReport方法(Ctrl+O),代码如下:

package com.test.test_one;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.ResourceCDN;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.model.TestAttribute;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.ChartLocation;
import com.aventstack.extentreports.reporter.configuration.Theme;
import org.testng.*;
import org.testng.xml.XmlSuite;
import java.io.File;
import java.util.*;

public class Unit_Test_Report implements IReporter {
   /* 生成报告路径与文件名 */
   private static final String OUTPUT_FOLDER = "test-output/";
   private static final String FILE_NAME = "index.html";
   /* 生成报告情况 */
   private ExtentReports extent;
   /* 初始化报告 */
   private void init() {
      /* 文件夹不存在时,创建文件夹 */
      File reportDir = new File(OUTPUT_FOLDER);
      if(!reportDir.exists() && !reportDir.isDirectory()){
             reportDir.mkdir();
      }
      ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
      htmlReporter.config().setDocumentTitle("单元测试报告");
      htmlReporter.config().setReportName("单元自动化测试报告");
      htmlReporter.config().setChartVisibilityOnOpen(true);
      htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
      htmlReporter.config().setTheme(Theme.DARK);
      htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);
      htmlReporter.config().setCSS(".node.level-1  ul{ display:none;} .node.level-1.active ul{display:block;}");
      extent = new ExtentReports();
      extent.attachReporter(htmlReporter);
      extent.setReportUsesManualConfiguration(true);
   }
   
   /* 报告生成时间 */
   private Date getTime(long millis) {
      Calendar calendar = Calendar.getInstance();
      calendar.setTimeInMillis(millis);
      return calendar.getTime();
   }

   private void buildTestNodes(ExtentTest extenttest,IResultMap tests, Status status) {
      /* 存在父节点时,获取父节点的标签 */
      String[] categories = new String[0];
      if(extenttest != null ){
         List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();
         categories = new String[categoryList.size()];
         for(int index = 0;index < categoryList.size();index++){
            categories[index] = categoryList.get(index).getName();
         }
      }
      ExtentTest test;
      if (tests.size() > 0) {
      /* 调整用例排序,按时间排序 */
      Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {
         @Override
         public int compare(ITestResult o1, ITestResult o2) {
            return o1.getStartMillis() < o2.getStartMillis()? -1:1;
         }
      });
      treeSet.addAll(tests.getAllResults());
      for (ITestResult result : treeSet) {
         Object[] parameters = result.getParameters();
         String name = "";
         /* 如果有参数,则使用参数的toString组合代替报告中的name*/
         for(Object param:parameters){
            name = param.toString();
         }
         if(name.length() > 0){
            if(name.length() > 50){
               name = name.substring(0,49)+"...";
            }
         }else{
            name = result.getMethod().getMethodName();
         }
         if(extenttest == null){
            test = extent.createTest(name);
         }else{
            /* 作为子节点进行创建时,设置同父节点的标签一致,便于报告检索 */
            test = extenttest.createNode(name).assignCategory(categories);
         }
         for (String group : result.getMethod().getGroups()){
            test.assignCategory(group);
         }
         test = extent.createTest(result.getMethod().getMethodName());
         List<String> outputList = Reporter.getOutput(result);
         for(String output:outputList)
            /* 将用例的log输出报告中 */
            test.debug(output);
         if (result.getThrowable() != null) {
            test.log(status, result.getThrowable());
         }else {
            test.log(status, "Test" + status.toString().toLowerCase() + "ed");
         }
         test.getModel().setStartTime(getTime(result.getStartMillis()));
         test.getModel().setEndTime(getTime(result.getEndMillis()));
         }
      }
   }
   @Override
   public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
      init();
      boolean createSuiteNode = false;
      if(suites.size() >= 1){
         createSuiteNode = true;
      }
      for (ISuite suite : suites) {
         Map<String, ISuiteResult> result = suite.getResults();
         /* 如果suite里面没有用例则不在生成到报告里 */
         if(result.size() == 0){
            continue;
         }
         /* 统计suite下成功、失败、跳过总用例数 */
         int suiteFailSize = 0;
         int suitePassSize = 0;
         int suiteSkipSize = 0;
         ExtentTest suiteTest = null;
         /* 存在多个suite情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点 */
         if(createSuiteNode){
            suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
         }
         boolean createSuiteResultNode = false;
         if(result.size() > 1){
            createSuiteResultNode = true;
         }
         for (ISuiteResult r : result.values()) {
            ExtentTest resultNode;
            ITestContext context = r.getTestContext();
            if(createSuiteResultNode){
            /*没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点*/
               if( null == suiteTest){
                  resultNode = extent.createTest(r.getTestContext().getName());
               }else{
                  resultNode = suiteTest.createNode(r.getTestContext().getName());
               }
            }else{
               resultNode = suiteTest;
            }
            if(resultNode != null){
               resultNode.getModel().setName(suite.getName() + ":" + r.getTestContext().getName());
               if(resultNode.getModel().hasCategory()){
                  resultNode.assignCategory(r.getTestContext().getName());
               }else{
                  resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
               }
               resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
               resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
               /* 统计SuiteResult下数据 */
               int passSize = r.getTestContext().getPassedTests().size();
               int failSize = r.getTestContext().getFailedTests().size();
               int skipSize = r.getTestContext().getSkippedTests().size();
               suitePassSize += passSize;
               suiteFailSize += failSize;
               suiteSkipSize += skipSize;
               if(failSize > 0){
                  resultNode.getModel().setStatus(Status.FAIL);
               }
               resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
            }
            buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
            buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
            buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
         }
         if(suiteTest != null){
            suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
            if(suiteFailSize > 0){
               suiteTest.getModel().setStatus(Status.FAIL);
            }
         }
      }
      for (String s : Reporter.getOutput()) {
         extent.setTestRunnerOutput(s);
      }
      extent.flush();
   }
}

1.7)src/main/java/com.test目录下新建Mathematics类

package com.test.modle;

public class Mathematics {
   public int getFactorial(int num){
      int result = 0;
      if(num == 1){
         result = num;
      }else {
         result = getFactorial(num - 1)*num;
      }
      return result;
   }
}

1.8)src/main/java/com.test目录下新建Test_Test_q类

package com.test.test_modle;
import com.test.modle.Test_q;
import org.testng.annotations.Test;

public class Test_Test_q {
   @Test
   public void test_print_Test_q_1(){
      Test_q test_q = new Test_q();
      test_q.print_Test_q();
   }
}

1.9)src/test/java/com.test_modle目录下新建Mathematics类(首个测试类一定要加@BeforeSuite与@BeforeClass)

package com.test.test_modle;

import com.test.modle.Mathematics;
import org.testng.Assert;
import org.testng.annotations.*;

public class Test_Mathematics {
   @BeforeSuite
   public void test_BeforeSuite(){
      System.out.println("开始测试modle套件");
   }
   @AfterSuite
   public void test_AfterSuite(){
      System.out.println("结束测试modle套件");
   }

   @BeforeClass
   public void test_BeforeClass(){
      System.out.println("开始测试Mathematics类");
   }

   @AfterClass
   public void test_AfterClass(){
      System.out.println("结束测试Mathematics类");
   }

   Mathematics mathematics = null;
   int num = 0;

   @Test
   public void test_getFactorial_1(){
      mathematics = new Mathematics();
      num = mathematics.getFactorial(1);
      Assert.assertEquals(num,1);
   }

   @Test
   public void test_getFactorial_2(){
      mathematics = new Mathematics();
      num = mathematics.getFactorial(5);
      Assert.assertEquals(num,1211);
   }
}

1.10)src/test/java/com.test_modle目录下新建Test_Test_q类(位于同一目录下所以只需要加@BeforeClass)

package com.test.test_modle;
import com.test.modle.Test_q;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class Test_Test_q {
   @BeforeClass
   public void test_BeforeClass(){
      System.out.println("开始测试Test_Test_q类");
   }

   @AfterClass
   public void test_AfterClass(){
      System.out.println("结束测试Test_Test_q类");
   }

   @Test
   public void test_print_Test_q_1(){
      Test_q test_q = new Test_q();
      test_q.print_Test_q();
   }
}

1.11)项目下新建testNG.xml文件,具体文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="modle测试套件">
   <test name="测试Mathematics类">
      <classes>
         <class name="com.test.test_modle.Test_Mathematics">
            <methods>
               <include name="test_getFactorial_1"/>
               <include name="test_getFactorial_2"/>
            </methods>
         </class>
      </classes>
   </test>

   <test name="测试Test_q类">
      <classes>
         <class name="com.test.test_modle.Test_Test_q">
            <methods>
               <include name="test_print_Test_q_1"/>
            </methods>
         </class>
      </classes>
   </test>
    
   <listeners>
      <listener class-name="com.test.test_one.Unit_Test_Report"></listener>
   </listeners>
</suite>

1.12)点击右上角【绿色三角】前的空格Edit Configurations

1.12.1)左上角选择项目,Code Coverage—"+"—选择Mathematics与测试Test_q类—Apply—OK 

1.13)生成报告设置:

1.13.1)run——edit Configurations——选择左侧要生成报告的类——Configuration——Listeners——勾选:Use default reporters——点击:OK
1.13.2)报告生成在项目的test-output目录下,由html与xml两种格式报告
1.13.3)右键testNG.xml文件,选择Run '...testNG.xml' with Coverage,查看报告

1.14)一个套件一定要加@BeforeSuite与@AfterSuite,套件下的类一定要加@BeforeClass与@AfterClass