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+ }
0 commit comments