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