View Javadoc

1   package org.apache.maven.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 org.apache.maven.surefire.util.PrettyPrintXMLWriter;
23  import org.codehaus.plexus.util.IOUtil;
24  import org.codehaus.plexus.util.xml.Xpp3Dom;
25  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
26  
27  import java.io.BufferedWriter;
28  import java.io.File;
29  import java.io.FileNotFoundException;
30  import java.io.FileOutputStream;
31  import java.io.OutputStreamWriter;
32  import java.io.PrintWriter;
33  import java.io.UnsupportedEncodingException;
34  import java.util.ArrayList;
35  import java.util.Collections;
36  import java.util.Enumeration;
37  import java.util.Iterator;
38  import java.util.List;
39  import java.util.Properties;
40  import java.util.StringTokenizer;
41  
42  /**
43   * XML format reporter.
44   *
45   * @author <a href="mailto:jruiz@exist.com">Johnny R. Ruiz III</a>
46   * @version $Id: XMLReporter.java 1063892 2011-01-26 22:04:57Z krosenvold $
47   */
48  public class XMLReporter
49      extends AbstractReporter
50  {
51      private static final String LS = System.getProperty( "line.separator" );
52  
53      private final File reportsDirectory;
54  
55      private final boolean deleteOnStarting;
56  
57      private final List results = Collections.synchronizedList( new ArrayList() );
58  
59      public XMLReporter( ReporterConfiguration reporterConfiguration )
60      {
61          super( reporterConfiguration );
62  
63          this.reportsDirectory = reporterConfiguration.getReportsDirectory();
64  
65          this.deleteOnStarting = reporterConfiguration.isForkWithTimeout();
66      }
67  
68  
69      public void writeMessage( String message )
70      {
71      }
72  
73      public void writeDetailMessage( String message )
74      {
75      }
76  
77  
78      public void testSetStarting( ReportEntry report )
79          throws ReporterException
80      {
81          super.testSetStarting( report );
82  
83          if ( deleteOnStarting )
84          {
85              final File reportFile = getReportFile( report );
86              deleteIfExisting( reportFile );
87          }
88      }
89  
90      public void testSetCompleted( ReportEntry report )
91          throws ReporterException
92      {
93          super.testSetCompleted( report );
94  
95          if ( isTimedOut() )
96          {
97              return;
98          }
99          long runTime = System.currentTimeMillis() - testSetStartTime;
100 
101         Xpp3Dom testSuite = createTestSuiteElement( report, runTime );
102 
103         showProperties( testSuite );
104 
105         testSuite.setAttribute( "tests", String.valueOf( this.getNumTests() ) );
106 
107         testSuite.setAttribute( "errors", String.valueOf( this.getNumErrors() ) );
108 
109         testSuite.setAttribute( "skipped", String.valueOf( this.getNumSkipped() ) );
110 
111         testSuite.setAttribute( "failures", String.valueOf( this.getNumFailures() ) );
112 
113         for ( Iterator i = results.iterator(); i.hasNext(); )
114         {
115             Xpp3Dom testcase = (Xpp3Dom) i.next();
116             testSuite.addChild( testcase );
117         }
118 
119         File reportFile = getReportFile( report );
120 
121         File reportDir = reportFile.getParentFile();
122 
123         reportDir.mkdirs();
124 
125         PrintWriter writer = null;
126 
127         try
128         {
129             writer = new PrintWriter(
130                 new BufferedWriter( new OutputStreamWriter( new FileOutputStream( reportFile ), "UTF-8" ) ) );
131 
132             writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + LS );
133 
134             Xpp3DomWriter.write( new PrettyPrintXMLWriter( writer ), testSuite );
135         }
136         catch ( UnsupportedEncodingException e )
137         {
138             throw new ReporterException( "Unable to use UTF-8 encoding", e );
139         }
140         catch ( FileNotFoundException e )
141         {
142             throw new ReporterException( "Unable to create file: " + e.getMessage(), e );
143         }
144 
145         finally
146         {
147             IOUtil.close( writer );
148         }
149     }
150 
151     private File getReportFile( ReportEntry report )
152     {
153         return new File( reportsDirectory, "TEST-" + report.getName() + ".xml" );
154     }
155 
156     private String getReportName( ReportEntry report )
157     {
158         String reportName;
159 
160         if ( report.getName().indexOf( "(" ) > 0 )
161         {
162             reportName = report.getName().substring( 0, report.getName().indexOf( "(" ) );
163         }
164         else
165         {
166             reportName = report.getName();
167         }
168         return reportName;
169     }
170 
171     public void testSucceeded( ReportEntry report )
172     {
173         super.testSucceeded( report );
174 
175         long runTime = getActualRunTime( report );
176 
177         Xpp3Dom testCase = createTestElement( report, runTime );
178 
179         results.add( testCase );
180     }
181 
182     private Xpp3Dom createTestElement( ReportEntry report, long runTime )
183     {
184         Xpp3Dom testCase = new Xpp3Dom( "testcase" );
185         testCase.setAttribute( "name", getReportName( report ) );
186         if ( report.getGroup() != null )
187         {
188             testCase.setAttribute( "group", report.getGroup() );
189         }
190         if ( report.getSourceName() != null )
191         {
192             testCase.setAttribute( "classname", report.getSourceName() );
193         }
194         testCase.setAttribute( "time", elapsedTimeAsString( runTime ) );
195         return testCase;
196     }
197 
198     private Xpp3Dom createTestSuiteElement( ReportEntry report, long runTime )
199     {
200         Xpp3Dom testCase = new Xpp3Dom( "testsuite" );
201         testCase.setAttribute( "name", getReportName( report ) );
202         if ( report.getGroup() != null )
203         {
204             testCase.setAttribute( "group", report.getGroup() );
205         }
206         testCase.setAttribute( "time", elapsedTimeAsString( runTime ) );
207         return testCase;
208     }
209 
210     public void testError( ReportEntry report, String stdOut, String stdErr )
211     {
212         super.testError( report, stdOut, stdErr );
213 
214         writeTestProblems( report, stdOut, stdErr, "error" );
215     }
216 
217     public void testFailed( ReportEntry report, String stdOut, String stdErr )
218     {
219         super.testFailed( report, stdOut, stdErr );
220 
221         writeTestProblems( report, stdOut, stdErr, "failure" );
222     }
223 
224     public void testSkipped( ReportEntry report )
225     {
226         super.testSkipped( report );
227         writeTestProblems( report, null, null, "skipped" );
228     }
229 
230     private void writeTestProblems( ReportEntry report, String stdOut, String stdErr, String name )
231     {
232         long runTime = getActualRunTime( report );
233 
234         Xpp3Dom testCase = createTestElement( report, runTime );
235 
236         Xpp3Dom element = createElement( testCase, name );
237 
238         String stackTrace = getStackTrace( report );
239 
240         Throwable t = null;
241         if ( report.getStackTraceWriter() != null )
242         {
243             t = report.getStackTraceWriter().getThrowable();
244         }
245 
246         if ( t != null )
247         {
248 
249             String message = t.getMessage();
250 
251             if ( message != null )
252             {
253                 element.setAttribute( "message", message );
254 
255                 element.setAttribute( "type", ( stackTrace.indexOf( ":" ) > -1
256                     ? stackTrace.substring( 0, stackTrace.indexOf( ":" ) )
257                     : stackTrace ) );
258             }
259             else
260             {
261                 element.setAttribute( "type", new StringTokenizer( stackTrace ).nextToken() );
262             }
263         }
264 
265         if ( stackTrace != null )
266         {
267             element.setValue( stackTrace );
268         }
269 
270         addOutputStreamElement( stdOut, "system-out", testCase );
271 
272         addOutputStreamElement( stdErr, "system-err", testCase );
273 
274         results.add( testCase );
275     }
276 
277     private void addOutputStreamElement( String stdOut, String name, Xpp3Dom testCase )
278     {
279         if ( stdOut != null && stdOut.trim().length() > 0 )
280         {
281             createElement( testCase, name ).setValue( stdOut );
282         }
283     }
284 
285     private Xpp3Dom createElement( Xpp3Dom element, String name )
286     {
287         Xpp3Dom component = new Xpp3Dom( name );
288 
289         element.addChild( component );
290 
291         return component;
292     }
293 
294     /**
295      * Adds system properties to the XML report.
296      *
297      * @param testSuite
298      */
299     private void showProperties( Xpp3Dom testSuite )
300     {
301         Xpp3Dom properties = createElement( testSuite, "properties" );
302 
303         Properties systemProperties = System.getProperties();
304 
305         if ( systemProperties != null )
306         {
307             Enumeration propertyKeys = systemProperties.propertyNames();
308 
309             while ( propertyKeys.hasMoreElements() )
310             {
311                 String key = (String) propertyKeys.nextElement();
312 
313                 String value = systemProperties.getProperty( key );
314 
315                 if ( value == null )
316                 {
317                     value = "null";
318                 }
319 
320                 Xpp3Dom property = createElement( properties, "property" );
321 
322                 property.setAttribute( "name", key );
323 
324                 property.setAttribute( "value", value );
325 
326             }
327         }
328     }
329 
330     public Iterator getResults()
331     {
332         return results.iterator();
333     }
334 
335     public void reset()
336     {
337         results.clear();
338         super.reset();
339     }
340 }