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
原文地址:https://www.cnblogs.com/andrew209/p/9160748.html
时间: 2024-10-13 10:37:45