Skip to content

Commit c5930bd

Browse files
committed
1.支持ExtentReport报告.
2。支持上传、下载 3.支持保留client
1 parent d249579 commit c5930bd

File tree

8 files changed

+318
-62
lines changed

8 files changed

+318
-62
lines changed

api-config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
<params>
99
<param name="test" value="value"></param>
1010
</params>
11+
<project_name>接口自动化测试报告demo</project_name>
1112
</root>

pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.sen.test</groupId>
55
<artifactId>api</artifactId>
6-
<version>0.0.1-SNAPSHOT</version>
6+
<version>0.0.2-SNAPSHOT</version>
77
<packaging>jar</packaging>
8-
<name>api</name>
8+
<name>接口测试自动化0.02版</name>
99
<url>http://maven.apache.org</url>
1010

1111
<properties>
@@ -103,6 +103,11 @@
103103
<version>3.0</version>
104104
<scope>test</scope>
105105
</dependency>
106+
<dependency>
107+
<groupId>com.aventstack</groupId>
108+
<artifactId>extentreports</artifactId>
109+
<version>3.0.3</version>
110+
</dependency>
106111
<dependency>
107112
<groupId>org.testng</groupId>
108113
<artifactId>testng</artifactId>

src/main/java/com/sen/api/beans/ApiDataBean.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class ApiDataBean extends BaseBean {
1111
private String verify;
1212
private String save;
1313
private String preParam;
14+
private int sleep;
1415

1516
public boolean isRun() {
1617
return run;
@@ -92,13 +93,19 @@ public void setPreParam(String preParam) {
9293
this.preParam = preParam;
9394
}
9495

96+
public int getSleep() {
97+
return sleep;
98+
}
99+
100+
public void setSleep(int sleep) {
101+
this.sleep = sleep;
102+
}
103+
95104
@Override
96105
public String toString() {
97106
// TODO Auto-generated method stub
98-
return String.format("desc:%s,method:%s,url:%s,param:%s",
99-
this.desc, this.method, this.url, this.param);
107+
return String.format("desc:%s,method:%s,url:%s,param:%s", this.desc,
108+
this.method, this.url, this.param);
100109
}
101-
102-
103110

104111
}

src/main/java/com/sen/api/configs/ApiConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.dom4j.Element;
1010
import org.dom4j.io.SAXReader;
1111

12+
import com.sen.api.utils.ReportUtil;
13+
1214
public class ApiConfig {
1315

1416
public ApiConfig(String configFilePath) throws DocumentException{
@@ -31,6 +33,10 @@ public ApiConfig(String configFilePath) throws DocumentException{
3133
headers.put(ele.attributeValue("name").trim(),
3234
ele.attributeValue("value").trim());
3335
});
36+
Element projectEle = rootElement.element("project_name");
37+
if(projectEle!=null){
38+
ReportUtil.setReportName(projectEle.getTextTrim());
39+
}
3440
}
3541
private String rootUrl;
3642

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

src/main/java/com/sen/api/utils/ReportUtil.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,23 @@
22

33
import org.testng.Reporter;
44

5+
import com.sen.api.utils.ReportUtil;
6+
import com.sen.api.utils.StringUtil;
7+
58
public class ReportUtil {
9+
private static String reportName = "自动化测试报告";
610
public static void log(String msg) {
711
Reporter.log(msg, true);
812
}
13+
14+
public static String getReportName() {
15+
return reportName;
16+
}
17+
18+
public static void setReportName(String reportName) {
19+
if(StringUtil.isNotEmpty(reportName)){
20+
ReportUtil.reportName = reportName;
21+
}
22+
}
923
}
1024

0 commit comments

Comments
 (0)