Skip to content

Commit caf58d5

Browse files
committed
[+]多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。
1 parent 6794198 commit caf58d5

2 files changed

Lines changed: 233 additions & 0 deletions

File tree

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

0 commit comments

Comments
 (0)