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.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.io.DirectoryScanner;
37  import org.xml.sax.SAXException;
38  
39  import static org.apache.maven.shared.utils.StringUtils.split;
40  
41  /**
42   *
43   */
44  public final class SurefireReportParser
45  {
46      private static final String INCLUDES = "*.xml";
47  
48      private static final String EXCLUDES =
49                      "*.txt, testng-failed.xml, testng-failures.xml, testng-results.xml, failsafe-summary*.xml";
50  
51      private static final int PCENT = 100;
52  
53      private final List<ReportTestSuite> testSuites = new ArrayList<>();
54  
55      private final NumberFormat numberFormat;
56  
57      private final ConsoleLogger consoleLogger;
58  
59      private final List<File> reportsDirectories;
60  
61      public SurefireReportParser( List<File> reportsDirectories, Locale locale, ConsoleLogger consoleLogger )
62      {
63          this.reportsDirectories = reportsDirectories;
64          numberFormat = NumberFormat.getInstance( locale );
65          this.consoleLogger = consoleLogger;
66      }
67  
68      public List<ReportTestSuite> parseXMLReportFiles()
69          throws MavenReportException
70      {
71          final Collection<File> xmlReportFiles = new ArrayList<>();
72          for ( File reportsDirectory : reportsDirectories )
73          {
74              if ( reportsDirectory.exists() )
75              {
76                  for ( String xmlReportFile : getIncludedFiles( reportsDirectory, INCLUDES, EXCLUDES ) )
77                  {
78                      xmlReportFiles.add( new File( reportsDirectory, xmlReportFile ) );
79                  }
80              }
81          }
82          final TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
83          for ( File aXmlReportFileList : xmlReportFiles )
84          {
85              try
86              {
87                  testSuites.addAll( parser.parse( aXmlReportFileList.getAbsolutePath() ) );
88              }
89              catch ( ParserConfigurationException e )
90              {
91                  throw new MavenReportException( "Error setting up parser for JUnit XML report", e );
92              }
93              catch ( SAXException e )
94              {
95                  throw new MavenReportException( "Error parsing JUnit XML report " + aXmlReportFileList, e );
96              }
97              catch ( IOException e )
98              {
99                  throw new MavenReportException( "Error reading JUnit XML report " + aXmlReportFileList, e );
100             }
101         }
102 
103         return testSuites;
104     }
105 
106     public Map<String, String> getSummary( List<ReportTestSuite> suites )
107     {
108         Map<String, String> totalSummary = new HashMap<>();
109 
110         int totalNumberOfTests = 0;
111 
112         int totalNumberOfErrors = 0;
113 
114         int totalNumberOfFailures = 0;
115 
116         int totalNumberOfSkipped = 0;
117 
118         float totalElapsedTime = 0.0f;
119 
120         for ( ReportTestSuite suite : suites )
121         {
122             totalNumberOfTests += suite.getNumberOfTests();
123 
124             totalNumberOfErrors += suite.getNumberOfErrors();
125 
126             totalNumberOfFailures += suite.getNumberOfFailures();
127 
128             totalNumberOfSkipped += suite.getNumberOfSkipped();
129 
130             totalElapsedTime += suite.getTimeElapsed();
131         }
132 
133         String totalPercentage =
134             computePercentage( totalNumberOfTests, totalNumberOfErrors, totalNumberOfFailures, totalNumberOfSkipped );
135 
136         totalSummary.put( "totalTests", Integer.toString( totalNumberOfTests ) );
137 
138         totalSummary.put( "totalErrors", Integer.toString( totalNumberOfErrors ) );
139 
140         totalSummary.put( "totalFailures", Integer.toString( totalNumberOfFailures ) );
141 
142         totalSummary.put( "totalSkipped", Integer.toString( totalNumberOfSkipped ) );
143 
144         totalSummary.put( "totalElapsedTime", numberFormat.format( totalElapsedTime ) );
145 
146         totalSummary.put( "totalPercentage", totalPercentage );
147 
148         return totalSummary;
149     }
150 
151     public NumberFormat getNumberFormat()
152     {
153         return numberFormat;
154     }
155 
156     public Map<String, List<ReportTestSuite>> getSuitesGroupByPackage( List<ReportTestSuite> testSuitesList )
157     {
158         Map<String, List<ReportTestSuite>> suitePackage = new HashMap<>();
159 
160         for ( ReportTestSuite suite : testSuitesList )
161         {
162             List<ReportTestSuite> suiteList = new ArrayList<>();
163 
164             if ( suitePackage.get( suite.getPackageName() ) != null )
165             {
166                 suiteList = suitePackage.get( suite.getPackageName() );
167             }
168 
169             suiteList.add( suite );
170 
171             suitePackage.put( suite.getPackageName(), suiteList );
172         }
173 
174         return suitePackage;
175     }
176 
177     public String computePercentage( int tests, int errors, int failures, int skipped )
178     {
179         float percentage =
180             tests == 0 ? 0 : ( (float) ( tests - errors - failures - skipped ) / (float) tests ) * PCENT;
181         return numberFormat.format( percentage );
182     }
183 
184     public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> testSuites )
185     {
186         List<ReportTestCase> failureDetails = new ArrayList<>();
187 
188         for ( ReportTestSuite suite : testSuites )
189         {
190             for ( ReportTestCase tCase : suite.getTestCases() )
191             {
192                 if ( !tCase.isSuccessful() )
193                 {
194                     failureDetails.add( tCase );
195                 }
196             }
197         }
198 
199         return failureDetails;
200     }
201 
202     /**
203      * Returns {@code true} if the specified directory contains at least one report file.
204      *
205      * @param directory the directory
206      * @return {@code true} if the specified directory contains at least one report file.
207      */
208     public static boolean hasReportFiles( File directory )
209     {
210         return directory != null && directory.isDirectory()
211             && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length != 0;
212     }
213 
214     private static String[] getIncludedFiles( File directory, String includes, String excludes )
215     {
216         DirectoryScanner scanner = new DirectoryScanner();
217 
218         scanner.setBasedir( directory );
219 
220         scanner.setIncludes( split( includes, "," ) );
221 
222         scanner.setExcludes( split( excludes, "," ) );
223 
224         scanner.scan();
225 
226         return scanner.getIncludedFiles();
227     }
228 }