View Javadoc
1   package org.apache.maven.plugin.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.shared.utils.logging.MessageBuilder;
23  import org.apache.maven.surefire.api.report.ReportEntry;
24  
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.List;
28  import java.util.Queue;
29  import java.util.concurrent.ConcurrentLinkedQueue;
30  
31  import static org.apache.maven.surefire.shared.utils.logging.MessageUtils.buffer;
32  import static org.apache.maven.surefire.api.report.CategorizedReportEntry.GROUP_PREFIX;
33  
34  /**
35   * Maintains per-thread test result state. Not thread safe.
36   */
37  public class TestSetStats
38  {
39      private static final String TESTS = "Tests ";
40      private static final String RUN = "run: ";
41      private static final String TESTS_RUN = "Tests run: ";
42      private static final String FAILURES = "Failures: ";
43      private static final String ERRORS = "Errors: ";
44      private static final String SKIPPED = "Skipped: ";
45      private static final String FAILURE_MARKER = " <<< FAILURE!";
46      private static final String IN_MARKER = " - in ";
47      private static final String COMMA = ", ";
48  
49      private final Queue<WrappedReportEntry> reportEntries = new ConcurrentLinkedQueue<>();
50  
51      private final boolean trimStackTrace;
52  
53      private final boolean plainFormat;
54  
55      private long testSetStartAt;
56  
57      private long testStartAt;
58  
59      private int completedCount;
60  
61      private int errors;
62  
63      private int failures;
64  
65      private int skipped;
66  
67      private long lastStartAt;
68  
69      public TestSetStats( boolean trimStackTrace, boolean plainFormat )
70      {
71          this.trimStackTrace = trimStackTrace;
72          this.plainFormat = plainFormat;
73      }
74  
75      public int getElapsedSinceTestSetStart()
76      {
77          return testSetStartAt > 0 ? (int) ( System.currentTimeMillis() - testSetStartAt ) : 0;
78      }
79  
80      public int getElapsedSinceLastStart()
81      {
82          return lastStartAt > 0 ? (int) ( System.currentTimeMillis() - lastStartAt ) : 0;
83      }
84  
85      public void testSetStart()
86      {
87          testSetStartAt = System.currentTimeMillis();
88          lastStartAt = testSetStartAt;
89      }
90  
91      public void testStart()
92      {
93          testStartAt = System.currentTimeMillis();
94          lastStartAt = testStartAt;
95      }
96  
97      private void finishTest( WrappedReportEntry reportEntry )
98      {
99          reportEntries.add( reportEntry );
100         incrementCompletedCount();
101         // SUREFIRE-398 skipped tests call endTest without calling testStarting
102         // if startTime = 0, set it to endTime, so the diff will be 0
103         if ( testStartAt == 0 )
104         {
105             testStartAt = System.currentTimeMillis();
106         }
107     }
108 
109     public void testSucceeded( WrappedReportEntry reportEntry )
110     {
111         finishTest( reportEntry );
112     }
113 
114     public void testError( WrappedReportEntry reportEntry )
115     {
116         errors += 1;
117         finishTest( reportEntry );
118     }
119 
120     public void testFailure( WrappedReportEntry reportEntry )
121     {
122         failures += 1;
123         finishTest( reportEntry );
124     }
125 
126     public void testSkipped( WrappedReportEntry reportEntry )
127     {
128         skipped += 1;
129         finishTest( reportEntry );
130     }
131 
132     public void reset()
133     {
134         completedCount = 0;
135         errors = 0;
136         failures = 0;
137         skipped = 0;
138 
139         for ( WrappedReportEntry entry : reportEntries )
140         {
141             entry.getStdout().free();
142             entry.getStdErr().free();
143         }
144 
145         reportEntries.clear();
146     }
147 
148     public int getCompletedCount()
149     {
150         return completedCount;
151     }
152 
153     public int getErrors()
154     {
155         return errors;
156     }
157 
158     public int getFailures()
159     {
160         return failures;
161     }
162 
163     public int getSkipped()
164     {
165         return skipped;
166     }
167 
168     private void incrementCompletedCount()
169     {
170         completedCount += 1;
171     }
172 
173     public String getTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
174     {
175         String summary = TESTS_RUN + completedCount
176                                  + COMMA
177                                  + FAILURES + failures
178                                  + COMMA
179                                  + ERRORS + errors
180                                  + COMMA
181                                  + SKIPPED + skipped
182                                  + COMMA
183                                  + reportEntry.getElapsedTimeVerbose();
184 
185         if ( failures > 0 || errors > 0 )
186         {
187             summary += FAILURE_MARKER;
188         }
189 
190         summary += IN_MARKER;
191         summary += phrasedClassName ? reportEntry.getReportNameWithGroup() : reportEntry.getNameWithGroup();
192 
193         return summary;
194     }
195 
196     public String getColoredTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
197     {
198         final boolean isSuccessful = failures == 0 && errors == 0 && skipped == 0;
199         final boolean isFailure = failures > 0;
200         final boolean isError = errors > 0;
201         final boolean isFailureOrError = isFailure | isError;
202         final boolean isSkipped = skipped > 0;
203         final  MessageBuilder builder = buffer();
204         if ( isSuccessful )
205         {
206             if ( completedCount == 0 )
207             {
208                 builder.strong( TESTS_RUN ).strong( completedCount );
209             }
210             else
211             {
212                 builder.success( TESTS_RUN ).success( completedCount );
213             }
214         }
215         else
216         {
217             if ( isFailureOrError )
218             {
219                 builder.failure( TESTS ).strong( RUN ).strong( completedCount );
220             }
221             else
222             {
223                 builder.warning( TESTS ).strong( RUN ).strong( completedCount );
224             }
225         }
226         builder.a( COMMA );
227         if ( isFailure )
228         {
229             builder.failure( FAILURES ).failure( failures );
230         }
231         else
232         {
233             builder.a( FAILURES ).a( failures );
234         }
235         builder.a( COMMA );
236         if ( isError )
237         {
238             builder.failure( ERRORS ).failure( errors );
239         }
240         else
241         {
242             builder.a( ERRORS ).a( errors );
243         }
244         builder.a( COMMA );
245         if ( isSkipped )
246         {
247             builder.warning( SKIPPED ).warning( skipped );
248         }
249         else
250         {
251             builder.a( SKIPPED ).a( skipped );
252         }
253         builder.a( COMMA )
254                 .a( reportEntry.getElapsedTimeVerbose() );
255         if ( isFailureOrError )
256         {
257             builder.failure( FAILURE_MARKER );
258         }
259         builder.a( IN_MARKER );
260         return concatenateWithTestGroup( builder, reportEntry, phrasedClassName );
261     }
262 
263     public List<String> getTestResults()
264     {
265         List<String> result = new ArrayList<>();
266         for ( WrappedReportEntry testResult : reportEntries )
267         {
268             if ( testResult.isErrorOrFailure() )
269             {
270                 result.add( testResult.getOutput( trimStackTrace ) );
271             }
272             else if ( plainFormat && testResult.isSkipped() )
273             {
274                 result.add( testResult.getSourceName() + " skipped" );
275             }
276             else if ( plainFormat && testResult.isSucceeded() )
277             {
278                 result.add( testResult.getElapsedTimeSummary() );
279             }
280         }
281         // This should be Map with an enum and the enums will be displayed with colors on console.
282         return result;
283     }
284 
285     public Collection<WrappedReportEntry> getReportEntries()
286     {
287         return reportEntries;
288     }
289 
290     /**
291      * Append the test set message for a report.
292      * e.g. "org.foo.BarTest ( of group )" or phrased text "test class description ( of group )".
293      *
294      * @param builder    MessageBuilder with preceded text inside
295      * @param report     report whose test set is starting
296      * @return the message
297      */
298     static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report, boolean phrasedClassName )
299     {
300         if ( phrasedClassName )
301         {
302             return builder.strong( report.getReportNameWithGroup() )
303                     .toString();
304         }
305         else
306         {
307             String testClass = report.getNameWithGroup();
308             int indexOfGroup = testClass.indexOf( GROUP_PREFIX );
309             int delimiter = testClass.lastIndexOf( '.', indexOfGroup == -1 ? testClass.length() : indexOfGroup );
310             String pkg = testClass.substring( 0, 1 + delimiter );
311             String cls = testClass.substring( 1 + delimiter );
312             return builder.a( pkg )
313                     .strong( cls )
314                     .toString();
315         }
316     }
317 }