blob: 869f58a5af9d06e51b3ba3d5adae09e65fbfa430 [file] [log] [blame]
package org.apache.maven.plugin.surefire.report;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.surefire.shared.utils.logging.MessageBuilder;
import org.apache.maven.surefire.api.report.ReportEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import static org.apache.maven.surefire.shared.utils.logging.MessageUtils.buffer;
import static org.apache.maven.surefire.api.report.CategorizedReportEntry.GROUP_PREFIX;
/**
* Maintains per-thread test result state. Not thread safe.
*/
public class TestSetStats
{
private static final String TESTS = "Tests ";
private static final String RUN = "run: ";
private static final String TESTS_RUN = "Tests run: ";
private static final String FAILURES = "Failures: ";
private static final String ERRORS = "Errors: ";
private static final String SKIPPED = "Skipped: ";
private static final String FAILURE_MARKER = " <<< FAILURE!";
private static final String IN_MARKER = " - in ";
private static final String COMMA = ", ";
private final Queue<WrappedReportEntry> reportEntries = new ConcurrentLinkedQueue<>();
private final boolean trimStackTrace;
private final boolean plainFormat;
private long testSetStartAt;
private long testStartAt;
private int completedCount;
private int errors;
private int failures;
private int skipped;
private long lastStartAt;
public TestSetStats( boolean trimStackTrace, boolean plainFormat )
{
this.trimStackTrace = trimStackTrace;
this.plainFormat = plainFormat;
}
public int getElapsedSinceTestSetStart()
{
return testSetStartAt > 0 ? (int) ( System.currentTimeMillis() - testSetStartAt ) : 0;
}
public int getElapsedSinceLastStart()
{
return lastStartAt > 0 ? (int) ( System.currentTimeMillis() - lastStartAt ) : 0;
}
public void testSetStart()
{
testSetStartAt = System.currentTimeMillis();
lastStartAt = testSetStartAt;
}
public void testStart()
{
testStartAt = System.currentTimeMillis();
lastStartAt = testStartAt;
}
private void finishTest( WrappedReportEntry reportEntry )
{
reportEntries.add( reportEntry );
incrementCompletedCount();
// SUREFIRE-398 skipped tests call endTest without calling testStarting
// if startTime = 0, set it to endTime, so the diff will be 0
if ( testStartAt == 0 )
{
testStartAt = System.currentTimeMillis();
}
}
public void testSucceeded( WrappedReportEntry reportEntry )
{
finishTest( reportEntry );
}
public void testError( WrappedReportEntry reportEntry )
{
errors += 1;
finishTest( reportEntry );
}
public void testFailure( WrappedReportEntry reportEntry )
{
failures += 1;
finishTest( reportEntry );
}
public void testSkipped( WrappedReportEntry reportEntry )
{
skipped += 1;
finishTest( reportEntry );
}
public void reset()
{
completedCount = 0;
errors = 0;
failures = 0;
skipped = 0;
for ( WrappedReportEntry entry : reportEntries )
{
entry.getStdout().free();
entry.getStdErr().free();
}
reportEntries.clear();
}
public int getCompletedCount()
{
return completedCount;
}
public int getErrors()
{
return errors;
}
public int getFailures()
{
return failures;
}
public int getSkipped()
{
return skipped;
}
private void incrementCompletedCount()
{
completedCount += 1;
}
public String getTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
{
String summary = TESTS_RUN + completedCount
+ COMMA
+ FAILURES + failures
+ COMMA
+ ERRORS + errors
+ COMMA
+ SKIPPED + skipped
+ COMMA
+ reportEntry.getElapsedTimeVerbose();
if ( failures > 0 || errors > 0 )
{
summary += FAILURE_MARKER;
}
summary += IN_MARKER;
summary += phrasedClassName ? reportEntry.getReportNameWithGroup() : reportEntry.getNameWithGroup();
return summary;
}
public String getColoredTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName )
{
final boolean isSuccessful = failures == 0 && errors == 0 && skipped == 0;
final boolean isFailure = failures > 0;
final boolean isError = errors > 0;
final boolean isFailureOrError = isFailure | isError;
final boolean isSkipped = skipped > 0;
final MessageBuilder builder = buffer();
if ( isSuccessful )
{
if ( completedCount == 0 )
{
builder.strong( TESTS_RUN ).strong( completedCount );
}
else
{
builder.success( TESTS_RUN ).success( completedCount );
}
}
else
{
if ( isFailureOrError )
{
builder.failure( TESTS ).strong( RUN ).strong( completedCount );
}
else
{
builder.warning( TESTS ).strong( RUN ).strong( completedCount );
}
}
builder.a( COMMA );
if ( isFailure )
{
builder.failure( FAILURES ).failure( failures );
}
else
{
builder.a( FAILURES ).a( failures );
}
builder.a( COMMA );
if ( isError )
{
builder.failure( ERRORS ).failure( errors );
}
else
{
builder.a( ERRORS ).a( errors );
}
builder.a( COMMA );
if ( isSkipped )
{
builder.warning( SKIPPED ).warning( skipped );
}
else
{
builder.a( SKIPPED ).a( skipped );
}
builder.a( COMMA )
.a( reportEntry.getElapsedTimeVerbose() );
if ( isFailureOrError )
{
builder.failure( FAILURE_MARKER );
}
builder.a( IN_MARKER );
return concatenateWithTestGroup( builder, reportEntry, phrasedClassName );
}
public List<String> getTestResults()
{
List<String> result = new ArrayList<>();
for ( WrappedReportEntry testResult : reportEntries )
{
if ( testResult.isErrorOrFailure() )
{
result.add( testResult.getOutput( trimStackTrace ) );
}
else if ( plainFormat && testResult.isSkipped() )
{
result.add( testResult.getSourceName() + " skipped" );
}
else if ( plainFormat && testResult.isSucceeded() )
{
result.add( testResult.getElapsedTimeSummary() );
}
}
// This should be Map with an enum and the enums will be displayed with colors on console.
return result;
}
public Collection<WrappedReportEntry> getReportEntries()
{
return reportEntries;
}
/**
* Append the test set message for a report.
* e.g. "org.foo.BarTest ( of group )" or phrased text "test class description ( of group )".
*
* @param builder MessageBuilder with preceded text inside
* @param report report whose test set is starting
* @return the message
*/
static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report, boolean phrasedClassName )
{
if ( phrasedClassName )
{
return builder.strong( report.getReportNameWithGroup() )
.toString();
}
else
{
String testClass = report.getNameWithGroup();
int indexOfGroup = testClass.indexOf( GROUP_PREFIX );
int delimiter = testClass.lastIndexOf( '.', indexOfGroup == -1 ? testClass.length() : indexOfGroup );
String pkg = testClass.substring( 0, 1 + delimiter );
String cls = testClass.substring( 1 + delimiter );
return builder.a( pkg )
.strong( cls )
.toString();
}
}
}