View Javadoc

1   package org.apache.maven.plugins.surefire.report;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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.Collections;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Locale;
31  import java.util.Map;
32  import org.apache.maven.reporting.MavenReportException;
33  import org.apache.maven.shared.utils.StringUtils;
34  import org.apache.maven.shared.utils.io.DirectoryScanner;
35  
36  import javax.xml.parsers.ParserConfigurationException;
37  
38  import org.xml.sax.SAXException;
39  
40  /**
41   *
42   */
43  public class SurefireReportParser
44  {
45      private static final String INCLUDES = "*.xml";
46  
47      private static final String EXCLUDES = "*.txt, testng-failed.xml, testng-failures.xml, testng-results.xml, failsafe-summary*.xml";
48  
49      private NumberFormat numberFormat = NumberFormat.getInstance();
50  
51      private List<File> reportsDirectories;
52  
53      private final List<ReportTestSuite> testSuites = new ArrayList<ReportTestSuite>();
54  
55      private static final int PCENT = 100;
56  
57      public SurefireReportParser()
58      {
59      }
60  
61      public SurefireReportParser( List<File> reportsDirectoriesFiles, Locale locale )
62      {
63          this.reportsDirectories = reportsDirectoriesFiles;
64  
65          setLocale( locale );
66      }
67  
68      public List<ReportTestSuite> parseXMLReportFiles()
69          throws MavenReportException
70      {
71          List<File> xmlReportFileList = new ArrayList<File>();
72          for ( File reportsDirectory : reportsDirectories )
73          {
74              if ( !reportsDirectory.exists() )
75              {
76                  continue;
77              }
78              String[] xmlReportFiles = getIncludedFiles( reportsDirectory, INCLUDES, EXCLUDES );
79              for ( String xmlReportFile : xmlReportFiles )
80              {
81                  File xmlReport = new File( reportsDirectory, xmlReportFile );
82                  xmlReportFileList.add( xmlReport );
83              }
84          }
85          TestSuiteXmlParser parser = new TestSuiteXmlParser();
86          for ( File aXmlReportFileList : xmlReportFileList )
87          {
88              Collection<ReportTestSuite> suites;
89  
90              try
91              {
92                  suites = parser.parse( aXmlReportFileList.getAbsolutePath() );
93              }
94              catch ( ParserConfigurationException e )
95              {
96                  throw new MavenReportException( "Error setting up parser for JUnit XML report", e );
97              }
98              catch ( SAXException e )
99              {
100                 throw new MavenReportException( "Error parsing JUnit XML report " + aXmlReportFileList, e );
101             }
102             catch ( IOException e )
103             {
104                 throw new MavenReportException( "Error reading JUnit XML report " + aXmlReportFileList, e );
105             }
106 
107             testSuites.addAll( suites );
108         }
109 
110         return testSuites;
111     }
112 
113     protected String parseTestSuiteName( String lineString )
114     {
115         return lineString.substring( lineString.lastIndexOf( "." ) + 1, lineString.length() );
116     }
117 
118     protected String parseTestSuitePackageName( String lineString )
119     {
120         return lineString.substring( lineString.indexOf( ":" ) + 2, lineString.lastIndexOf( "." ) );
121     }
122 
123     protected String parseTestCaseName( String lineString )
124     {
125         return lineString.substring( 0, lineString.indexOf( "(" ) );
126     }
127 
128     public Map<String, String> getSummary( List<ReportTestSuite> suites )
129     {
130         Map<String, String> totalSummary = new HashMap<String, String>();
131 
132         int totalNumberOfTests = 0;
133 
134         int totalNumberOfErrors = 0;
135 
136         int totalNumberOfFailures = 0;
137 
138         int totalNumberOfSkipped = 0;
139 
140         float totalElapsedTime = 0.0f;
141 
142         for ( ReportTestSuite suite : suites )
143         {
144             totalNumberOfTests += suite.getNumberOfTests();
145 
146             totalNumberOfErrors += suite.getNumberOfErrors();
147 
148             totalNumberOfFailures += suite.getNumberOfFailures();
149 
150             totalNumberOfSkipped += suite.getNumberOfSkipped();
151 
152             totalElapsedTime += suite.getTimeElapsed();
153         }
154 
155         String totalPercentage =
156             computePercentage( totalNumberOfTests, totalNumberOfErrors, totalNumberOfFailures, totalNumberOfSkipped );
157 
158         totalSummary.put( "totalTests", Integer.toString( totalNumberOfTests ) );
159 
160         totalSummary.put( "totalErrors", Integer.toString( totalNumberOfErrors ) );
161 
162         totalSummary.put( "totalFailures", Integer.toString( totalNumberOfFailures ) );
163 
164         totalSummary.put( "totalSkipped", Integer.toString( totalNumberOfSkipped ) );
165 
166         totalSummary.put( "totalElapsedTime", numberFormat.format( totalElapsedTime ) );
167 
168         totalSummary.put( "totalPercentage", totalPercentage );
169 
170         return totalSummary;
171     }
172 
173     public void setReportsDirectory( File reportsDirectory )
174     {
175         this.reportsDirectories = Collections.singletonList( reportsDirectory );
176     }
177 
178     public final void setLocale( Locale locale )
179     {
180         numberFormat = NumberFormat.getInstance( locale );
181     }
182 
183     public NumberFormat getNumberFormat()
184     {
185         return this.numberFormat;
186     }
187 
188     public Map<String, List<ReportTestSuite>> getSuitesGroupByPackage( List<ReportTestSuite> testSuitesList )
189     {
190         Map<String, List<ReportTestSuite>> suitePackage = new HashMap<String, List<ReportTestSuite>>();
191 
192         for ( ReportTestSuite suite : testSuitesList )
193         {
194             List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
195 
196             if ( suitePackage.get( suite.getPackageName() ) != null )
197             {
198                 suiteList = suitePackage.get( suite.getPackageName() );
199             }
200 
201             suiteList.add( suite );
202 
203             suitePackage.put( suite.getPackageName(), suiteList );
204         }
205 
206         return suitePackage;
207     }
208 
209     public String computePercentage( int tests, int errors, int failures, int skipped )
210     {
211         float percentage;
212         if ( tests == 0 )
213         {
214             percentage = 0;
215         }
216         else
217         {
218             percentage = ( (float) ( tests - errors - failures - skipped ) / (float) tests ) * PCENT;
219         }
220 
221         return numberFormat.format( percentage );
222     }
223 
224     public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> testSuitesList )
225     {
226         List<ReportTestCase> failureDetailList = new ArrayList<ReportTestCase>();
227 
228         for ( ReportTestSuite suite : testSuitesList )
229         {
230             List<ReportTestCase> testCaseList = suite.getTestCases();
231 
232             if ( testCaseList != null )
233             {
234                 for ( ReportTestCase tCase : testCaseList )
235                 {
236 
237                     if ( tCase.getFailure() != null )
238                     {
239                         failureDetailList.add( tCase );
240                     }
241                 }
242             }
243         }
244 
245         return failureDetailList;
246     }
247 
248     /**
249      * Returns {@code true} if the specified directory contains at least one report file.
250      *
251      * @param directory the directory
252      * @return {@code true} if the specified directory contains at least one report file.
253      */
254     public static boolean hasReportFiles( File directory )
255     {
256         return directory != null && directory.isDirectory()
257             && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length > 0;
258     }
259 
260     private static String[] getIncludedFiles( File directory, String includes, String excludes )
261     {
262         DirectoryScanner scanner = new DirectoryScanner();
263 
264         scanner.setBasedir( directory );
265 
266         scanner.setIncludes( StringUtils.split( includes, "," ) );
267 
268         scanner.setExcludes( StringUtils.split( excludes, "," ) );
269 
270         scanner.scan();
271 
272         return scanner.getIncludedFiles();
273     }
274 }