1 package org.apache.maven.plugins.surefire.report;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.text.NumberFormat;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31
32 import javax.xml.parsers.ParserConfigurationException;
33
34 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
35 import org.apache.maven.reporting.MavenReportException;
36 import org.apache.maven.shared.utils.StringUtils;
37 import org.apache.maven.shared.utils.io.DirectoryScanner;
38 import org.xml.sax.SAXException;
39
40 import static java.util.Collections.singletonList;
41
42
43
44
45 public final class SurefireReportParser
46 {
47 private static final String INCLUDES = "*.xml";
48
49 private static final String EXCLUDES =
50 "*.txt, testng-failed.xml, testng-failures.xml, testng-results.xml, failsafe-summary*.xml";
51
52 private static final int PCENT = 100;
53
54 private final List<ReportTestSuite> testSuites = new ArrayList<ReportTestSuite>();
55
56 private final NumberFormat numberFormat;
57
58 private final ConsoleLogger consoleLogger;
59
60 private List<File> reportsDirectories;
61
62 public SurefireReportParser( List<File> reportsDirectories, Locale locale, ConsoleLogger consoleLogger )
63 {
64 this.reportsDirectories = reportsDirectories;
65 numberFormat = NumberFormat.getInstance( locale );
66 this.consoleLogger = consoleLogger;
67 }
68
69 public List<ReportTestSuite> parseXMLReportFiles()
70 throws MavenReportException
71 {
72 final Collection<File> xmlReportFiles = new ArrayList<File>();
73 for ( File reportsDirectory : reportsDirectories )
74 {
75 if ( reportsDirectory.exists() )
76 {
77 for ( String xmlReportFile : getIncludedFiles( reportsDirectory, INCLUDES, EXCLUDES ) )
78 {
79 xmlReportFiles.add( new File( reportsDirectory, xmlReportFile ) );
80 }
81 }
82 }
83 final TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
84 for ( File aXmlReportFileList : xmlReportFiles )
85 {
86 try
87 {
88 testSuites.addAll( parser.parse( aXmlReportFileList.getAbsolutePath() ) );
89 }
90 catch ( ParserConfigurationException e )
91 {
92 throw new MavenReportException( "Error setting up parser for JUnit XML report", e );
93 }
94 catch ( SAXException e )
95 {
96 throw new MavenReportException( "Error parsing JUnit XML report " + aXmlReportFileList, e );
97 }
98 catch ( IOException e )
99 {
100 throw new MavenReportException( "Error reading JUnit XML report " + aXmlReportFileList, e );
101 }
102 }
103
104 return testSuites;
105 }
106
107 protected String parseTestSuiteName( String lineString )
108 {
109 return lineString.substring( lineString.lastIndexOf( "." ) + 1, lineString.length() );
110 }
111
112 protected String parseTestSuitePackageName( String lineString )
113 {
114 return lineString.substring( lineString.indexOf( ":" ) + 2, lineString.lastIndexOf( "." ) );
115 }
116
117 protected String parseTestCaseName( String lineString )
118 {
119 return lineString.substring( 0, lineString.indexOf( "(" ) );
120 }
121
122 public Map<String, String> getSummary( List<ReportTestSuite> suites )
123 {
124 Map<String, String> totalSummary = new HashMap<String, String>();
125
126 int totalNumberOfTests = 0;
127
128 int totalNumberOfErrors = 0;
129
130 int totalNumberOfFailures = 0;
131
132 int totalNumberOfSkipped = 0;
133
134 float totalElapsedTime = 0.0f;
135
136 for ( ReportTestSuite suite : suites )
137 {
138 totalNumberOfTests += suite.getNumberOfTests();
139
140 totalNumberOfErrors += suite.getNumberOfErrors();
141
142 totalNumberOfFailures += suite.getNumberOfFailures();
143
144 totalNumberOfSkipped += suite.getNumberOfSkipped();
145
146 totalElapsedTime += suite.getTimeElapsed();
147 }
148
149 String totalPercentage =
150 computePercentage( totalNumberOfTests, totalNumberOfErrors, totalNumberOfFailures, totalNumberOfSkipped );
151
152 totalSummary.put( "totalTests", Integer.toString( totalNumberOfTests ) );
153
154 totalSummary.put( "totalErrors", Integer.toString( totalNumberOfErrors ) );
155
156 totalSummary.put( "totalFailures", Integer.toString( totalNumberOfFailures ) );
157
158 totalSummary.put( "totalSkipped", Integer.toString( totalNumberOfSkipped ) );
159
160 totalSummary.put( "totalElapsedTime", numberFormat.format( totalElapsedTime ) );
161
162 totalSummary.put( "totalPercentage", totalPercentage );
163
164 return totalSummary;
165 }
166
167 public void setReportsDirectory( File reportsDirectory )
168 {
169 reportsDirectories = singletonList( reportsDirectory );
170 }
171
172 public NumberFormat getNumberFormat()
173 {
174 return numberFormat;
175 }
176
177 public Map<String, List<ReportTestSuite>> getSuitesGroupByPackage( List<ReportTestSuite> testSuitesList )
178 {
179 Map<String, List<ReportTestSuite>> suitePackage = new HashMap<String, List<ReportTestSuite>>();
180
181 for ( ReportTestSuite suite : testSuitesList )
182 {
183 List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
184
185 if ( suitePackage.get( suite.getPackageName() ) != null )
186 {
187 suiteList = suitePackage.get( suite.getPackageName() );
188 }
189
190 suiteList.add( suite );
191
192 suitePackage.put( suite.getPackageName(), suiteList );
193 }
194
195 return suitePackage;
196 }
197
198 public String computePercentage( int tests, int errors, int failures, int skipped )
199 {
200 float percentage =
201 tests == 0 ? 0 : ( (float) ( tests - errors - failures - skipped ) / (float) tests ) * PCENT;
202 return numberFormat.format( percentage );
203 }
204
205 public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> testSuites )
206 {
207 List<ReportTestCase> failureDetailList = new ArrayList<ReportTestCase>();
208
209 for ( ReportTestSuite suite : testSuites )
210 {
211 List<ReportTestCase> testCases = suite.getTestCases();
212 if ( testCases != null )
213 {
214 for ( ReportTestCase tCase : testCases )
215 {
216 if ( tCase.hasFailure() )
217 {
218 failureDetailList.add( tCase );
219 }
220 }
221 }
222 }
223
224 return failureDetailList;
225 }
226
227
228
229
230
231
232
233 public static boolean hasReportFiles( File directory )
234 {
235 return directory != null && directory.isDirectory()
236 && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length != 0;
237 }
238
239 private static String[] getIncludedFiles( File directory, String includes, String excludes )
240 {
241 DirectoryScanner scanner = new DirectoryScanner();
242
243 scanner.setBasedir( directory );
244
245 scanner.setIncludes( StringUtils.split( includes, "," ) );
246
247 scanner.setExcludes( StringUtils.split( excludes, "," ) );
248
249 scanner.scan();
250
251 return scanner.getIncludedFiles();
252 }
253 }