| 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(); |
| } |
| } |
| } |