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 =
48                      "*.txt, testng-failed.xml, testng-failures.xml, testng-results.xml, failsafe-summary*.xml";
49  
50      private NumberFormat numberFormat = NumberFormat.getInstance();
51  
52      private List<File> reportsDirectories;
53  
54      private final List<ReportTestSuite> testSuites = new ArrayList<ReportTestSuite>();
55  
56      private static final int PCENT = 100;
57  
58      public SurefireReportParser()
59      {
60      }
61  
62      public SurefireReportParser( List<File> reportsDirectoriesFiles, Locale locale )
63      {
64          this.reportsDirectories = reportsDirectoriesFiles;
65  
66          setLocale( locale );
67      }
68  
69      public List<ReportTestSuite> parseXMLReportFiles()
70          throws MavenReportException
71      {
72          List<File> xmlReportFileList = new ArrayList<File>();
73          for ( File reportsDirectory : reportsDirectories )
74          {
75              if ( !reportsDirectory.exists() )
76              {
77                  continue;
78              }
79              String[] xmlReportFiles = getIncludedFiles( reportsDirectory, INCLUDES, EXCLUDES );
80              for ( String xmlReportFile : xmlReportFiles )
81              {
82                  File xmlReport = new File( reportsDirectory, xmlReportFile );
83                  xmlReportFileList.add( xmlReport );
84              }
85          }
86          TestSuiteXmlParser parser = new TestSuiteXmlParser();
87          for ( File aXmlReportFileList : xmlReportFileList )
88          {
89              Collection<ReportTestSuite> suites;
90  
91              try
92              {
93                  suites = parser.parse( aXmlReportFileList.getAbsolutePath() );
94              }
95              catch ( ParserConfigurationException e )
96              {
97                  throw new MavenReportException( "Error setting up parser for JUnit XML report", e );
98              }
99              catch ( SAXException e )
100             {
101                 throw new MavenReportException( "Error parsing JUnit XML report " + aXmlReportFileList, e );
102             }
103             catch ( IOException e )
104             {
105                 throw new MavenReportException( "Error reading JUnit XML report " + aXmlReportFileList, e );
106             }
107 
108             testSuites.addAll( suites );
109         }
110 
111         return testSuites;
112     }
113 
114     protected String parseTestSuiteName( String lineString )
115     {
116         return lineString.substring( lineString.lastIndexOf( "." ) + 1, lineString.length() );
117     }
118 
119     protected String parseTestSuitePackageName( String lineString )
120     {
121         return lineString.substring( lineString.indexOf( ":" ) + 2, lineString.lastIndexOf( "." ) );
122     }
123 
124     protected String parseTestCaseName( String lineString )
125     {
126         return lineString.substring( 0, lineString.indexOf( "(" ) );
127     }
128 
129     public Map<String, String> getSummary( List<ReportTestSuite> suites )
130     {
131         Map<String, String> totalSummary = new HashMap<String, String>();
132 
133         int totalNumberOfTests = 0;
134 
135         int totalNumberOfErrors = 0;
136 
137         int totalNumberOfFailures = 0;
138 
139         int totalNumberOfSkipped = 0;
140 
141         float totalElapsedTime = 0.0f;
142 
143         for ( ReportTestSuite suite : suites )
144         {
145             totalNumberOfTests += suite.getNumberOfTests();
146 
147             totalNumberOfErrors += suite.getNumberOfErrors();
148 
149             totalNumberOfFailures += suite.getNumberOfFailures();
150 
151             totalNumberOfSkipped += suite.getNumberOfSkipped();
152 
153             totalElapsedTime += suite.getTimeElapsed();
154         }
155 
156         String totalPercentage =
157             computePercentage( totalNumberOfTests, totalNumberOfErrors, totalNumberOfFailures, totalNumberOfSkipped );
158 
159         totalSummary.put( "totalTests", Integer.toString( totalNumberOfTests ) );
160 
161         totalSummary.put( "totalErrors", Integer.toString( totalNumberOfErrors ) );
162 
163         totalSummary.put( "totalFailures", Integer.toString( totalNumberOfFailures ) );
164 
165         totalSummary.put( "totalSkipped", Integer.toString( totalNumberOfSkipped ) );
166 
167         totalSummary.put( "totalElapsedTime", numberFormat.format( totalElapsedTime ) );
168 
169         totalSummary.put( "totalPercentage", totalPercentage );
170 
171         return totalSummary;
172     }
173 
174     public void setReportsDirectory( File reportsDirectory )
175     {
176         this.reportsDirectories = Collections.singletonList( reportsDirectory );
177     }
178 
179     public final void setLocale( Locale locale )
180     {
181         numberFormat = NumberFormat.getInstance( locale );
182     }
183 
184     public NumberFormat getNumberFormat()
185     {
186         return this.numberFormat;
187     }
188 
189     public Map<String, List<ReportTestSuite>> getSuitesGroupByPackage( List<ReportTestSuite> testSuitesList )
190     {
191         Map<String, List<ReportTestSuite>> suitePackage = new HashMap<String, List<ReportTestSuite>>();
192 
193         for ( ReportTestSuite suite : testSuitesList )
194         {
195             List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
196 
197             if ( suitePackage.get( suite.getPackageName() ) != null )
198             {
199                 suiteList = suitePackage.get( suite.getPackageName() );
200             }
201 
202             suiteList.add( suite );
203 
204             suitePackage.put( suite.getPackageName(), suiteList );
205         }
206 
207         return suitePackage;
208     }
209 
210     public String computePercentage( int tests, int errors, int failures, int skipped )
211     {
212         float percentage;
213         if ( tests == 0 )
214         {
215             percentage = 0;
216         }
217         else
218         {
219             percentage = ( (float) ( tests - errors - failures - skipped ) / (float) tests ) * PCENT;
220         }
221 
222         return numberFormat.format( percentage );
223     }
224 
225     public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> testSuitesList )
226     {
227         List<ReportTestCase> failureDetailList = new ArrayList<ReportTestCase>();
228 
229         for ( ReportTestSuite suite : testSuitesList )
230         {
231             List<ReportTestCase> testCaseList = suite.getTestCases();
232 
233             if ( testCaseList != null )
234             {
235                 for ( ReportTestCase tCase : testCaseList )
236                 {
237 
238                     if ( tCase.getFailure() != null )
239                     {
240                         failureDetailList.add( tCase );
241                     }
242                 }
243             }
244         }
245 
246         return failureDetailList;
247     }
248 
249     /**
250      * Returns {@code true} if the specified directory contains at least one report file.
251      *
252      * @param directory the directory
253      * @return {@code true} if the specified directory contains at least one report file.
254      */
255     public static boolean hasReportFiles( File directory )
256     {
257         return directory != null && directory.isDirectory()
258             && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length > 0;
259     }
260 
261     private static String[] getIncludedFiles( File directory, String includes, String excludes )
262     {
263         DirectoryScanner scanner = new DirectoryScanner();
264 
265         scanner.setBasedir( directory );
266 
267         scanner.setIncludes( StringUtils.split( includes, "," ) );
268 
269         scanner.setExcludes( StringUtils.split( excludes, "," ) );
270 
271         scanner.scan();
272 
273         return scanner.getIncludedFiles();
274     }
275 }