You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by so...@apache.org on 2018/05/05 12:57:27 UTC
[maven-surefire] 04/10: Copy current sources from
junit-platform-surefire-provider
This is an automated email from the ASF dual-hosted git repository.
sor pushed a commit to branch 1330
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit 5976a8cbd6e9289198c8a882d99fb9d8f931435e
Author: Christian Stein <so...@gmail.com>
AuthorDate: Thu May 3 11:04:45 2018 +0200
Copy current sources from junit-platform-surefire-provider
This commit includes enhancements and bug fixes that were applied since
the initial code donation.
https://issues.apache.org/jira/browse/SUREFIRE-1330
---
.../junitplatform/JUnitPlatformProvider.java | 137 ++++--
.../surefire/junitplatform/RunListenerAdapter.java | 188 ++++++--
.../surefire/junitplatform/TestMethodFilter.java | 60 +++
.../junitplatform/TestPlanScannerFilter.java | 18 +-
.../junitplatform/JUnitPlatformProviderTests.java | 537 +++++++++++++++++++--
.../junitplatform/RunListenerAdapterTests.java | 400 +++++++++++++--
.../junitplatform/TestMethodFilterTests.java | 105 ++++
.../junitplatform/TestPlanScannerFilterTests.java | 30 +-
8 files changed, 1277 insertions(+), 198 deletions(-)
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
index 7f58921..510266e 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
@@ -19,35 +19,45 @@ package org.apache.maven.surefire.junitplatform;
* under the License.
*/
+import static java.util.Collections.emptyMap;
+import static java.util.stream.Collectors.toList;
+import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
+import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
import org.apache.maven.surefire.providerapi.AbstractProvider;
import org.apache.maven.surefire.providerapi.ProviderParameters;
+import org.apache.maven.surefire.report.ConsoleOutputCapture;
+import org.apache.maven.surefire.report.ConsoleOutputReceiver;
import org.apache.maven.surefire.report.ReporterException;
import org.apache.maven.surefire.report.ReporterFactory;
import org.apache.maven.surefire.report.RunListener;
-import org.apache.maven.surefire.report.SimpleReportEntry;
import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.ScanResult;
import org.apache.maven.surefire.util.TestsToRun;
+import org.junit.platform.commons.util.Preconditions;
+import org.junit.platform.commons.util.StringUtils;
import org.junit.platform.engine.Filter;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TagFilter;
+import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
-import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
-
-/**
- * @since 1.0
- */
public class JUnitPlatformProvider
extends AbstractProvider
{
@@ -61,6 +71,8 @@ public class JUnitPlatformProvider
static final String INCLUDE_TAGS = "includeTags";
+ static final String CONFIGURATION_PARAMETERS = "configurationParameters";
+
static final String EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED = "The " + INCLUDE_GROUPS + " and " + INCLUDE_TAGS
+ " parameters (or the " + EXCLUDE_GROUPS + " and " + EXCLUDE_TAGS + " parameters) are synonyms - "
+ "only one of each is allowed (though neither is required).";
@@ -69,9 +81,11 @@ public class JUnitPlatformProvider
private final Launcher launcher;
- final Filter<?>[] includeAndExcludeFilters;
+ final Filter<?>[] filters;
- public JUnitPlatformProvider( ProviderParameters parameters )
+ final Map<String, String> configurationParameters;
+
+ JUnitPlatformProvider( ProviderParameters parameters )
{
this( parameters, LauncherFactory.create() );
}
@@ -80,7 +94,8 @@ public class JUnitPlatformProvider
{
this.parameters = parameters;
this.launcher = launcher;
- this.includeAndExcludeFilters = getIncludeAndExcludeFilters();
+ this.filters = getFilters();
+ this.configurationParameters = getConfigurationParameters();
Logger.getLogger( "org.junit" ).setLevel( Level.WARNING );
}
@@ -92,7 +107,7 @@ public class JUnitPlatformProvider
@Override
public RunResult invoke( Object forkTestSet )
- throws TestSetFailedException, ReporterException, InvocationTargetException
+ throws TestSetFailedException, ReporterException
{
if ( forkTestSet instanceof TestsToRun )
{
@@ -114,8 +129,9 @@ public class JUnitPlatformProvider
private TestsToRun scanClasspath()
{
- TestsToRun scannedClasses = parameters.getScanResult().applyFilter(
- new TestPlanScannerFilter( launcher, includeAndExcludeFilters ), parameters.getTestClassLoader() );
+ TestPlanScannerFilter filter = new TestPlanScannerFilter( launcher, filters );
+ ScanResult scanResult = parameters.getScanResult();
+ TestsToRun scannedClasses = scanResult.applyFilter( filter, parameters.getTestClassLoader() );
return parameters.getRunOrderCalculator().orderTestClasses( scannedClasses );
}
@@ -126,12 +142,9 @@ public class JUnitPlatformProvider
try
{
RunListener runListener = reporterFactory.createReporter();
- launcher.registerTestExecutionListeners( new RunListenerAdapter( runListener ) );
-
- for ( Class<?> testClass : testsToRun )
- {
- invokeSingleClass( testClass, runListener );
- }
+ ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) runListener );
+ LauncherDiscoveryRequest discoveryRequest = buildLauncherDiscoveryRequest( testsToRun );
+ launcher.execute( discoveryRequest, new RunListenerAdapter( runListener ) );
}
finally
{
@@ -140,40 +153,70 @@ public class JUnitPlatformProvider
return runResult;
}
- private void invokeSingleClass( Class<?> testClass, RunListener runListener )
+ private LauncherDiscoveryRequest buildLauncherDiscoveryRequest( TestsToRun testsToRun )
{
- SimpleReportEntry classEntry = new SimpleReportEntry( getClass().getName(), testClass.getName() );
- runListener.testSetStarting( classEntry );
-
- LauncherDiscoveryRequest discoveryRequest = request().selectors( selectClass( testClass ) ).filters(
- includeAndExcludeFilters ).build();
- launcher.execute( discoveryRequest );
-
- runListener.testSetCompleted( classEntry );
+ LauncherDiscoveryRequestBuilder builder =
+ request().filters( filters ).configurationParameters( configurationParameters );
+ for ( Class<?> testClass : testsToRun )
+ {
+ builder.selectors( selectClass( testClass ) );
+ }
+ return builder.build();
}
- private Filter<?>[] getIncludeAndExcludeFilters()
+ private Filter<?>[] getFilters()
{
List<Filter<?>> filters = new ArrayList<>();
- Optional<List<String>> includes = getGroupsOrTags( getPropertiesList( INCLUDE_GROUPS ),
- getPropertiesList( INCLUDE_TAGS ) );
+ Optional<List<String>> includes =
+ getGroupsOrTags( getPropertiesList( INCLUDE_GROUPS ), getPropertiesList( INCLUDE_TAGS ) );
includes.map( TagFilter::includeTags ).ifPresent( filters::add );
- Optional<List<String>> excludes = getGroupsOrTags( getPropertiesList( EXCLUDE_GROUPS ),
- getPropertiesList( EXCLUDE_TAGS ) );
+ Optional<List<String>> excludes =
+ getGroupsOrTags( getPropertiesList( EXCLUDE_GROUPS ), getPropertiesList( EXCLUDE_TAGS ) );
excludes.map( TagFilter::excludeTags ).ifPresent( filters::add );
- return filters.toArray( new Filter<?>[filters.size()] );
+ TestListResolver testListResolver = parameters.getTestRequest().getTestListResolver();
+ if ( !testListResolver.isEmpty() )
+ {
+ filters.add( new TestMethodFilter( testListResolver ) );
+ }
+
+ return filters.toArray( new Filter<?>[0] );
+ }
+
+ private Map<String, String> getConfigurationParameters()
+ {
+ String content = parameters.getProviderProperties().get( CONFIGURATION_PARAMETERS );
+ if ( content == null )
+ {
+ return emptyMap();
+ }
+ try ( StringReader reader = new StringReader( content ) )
+ {
+ Map<String, String> result = new HashMap<>();
+ Properties props = new Properties();
+ props.load( reader );
+ props.stringPropertyNames().forEach( key -> result.put( key, props.getProperty( key ) ) );
+ return result;
+ }
+ catch ( IOException ex )
+ {
+ throw new UncheckedIOException( "Error reading " + CONFIGURATION_PARAMETERS, ex );
+ }
}
private Optional<List<String>> getPropertiesList( String key )
{
List<String> compoundProperties = null;
String property = parameters.getProviderProperties().get( key );
- if ( property != null )
+ if ( StringUtils.isNotBlank( property ) )
{
- compoundProperties = Arrays.asList( property.split( "[, ]+" ) );
+ compoundProperties =
+ Arrays.stream( property.split( "[,]+" ) )
+ .filter( StringUtils::isNotBlank )
+ .map( String::trim )
+ .collect( toList() );
}
return Optional.ofNullable( compoundProperties );
}
@@ -182,10 +225,7 @@ public class JUnitPlatformProvider
{
Optional<List<String>> elements = Optional.empty();
- if ( groups.isPresent() && tags.isPresent() )
- {
- throw new IllegalStateException( EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED );
- }
+ Preconditions.condition(!groups.isPresent() || !tags.isPresent(), EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED );
if ( groups.isPresent() )
{
@@ -198,5 +238,4 @@ public class JUnitPlatformProvider
return elements;
}
-
}
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
index 9191864..71a70c3 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
@@ -24,6 +24,8 @@ import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED;
import static org.junit.platform.engine.TestExecutionResult.Status.FAILED;
import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.surefire.report.PojoStackTraceWriter;
import org.apache.maven.surefire.report.RunListener;
@@ -36,6 +38,7 @@ import org.junit.platform.engine.support.descriptor.MethodSource;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.listeners.LegacyReportingUtils;
/**
* @since 1.0
@@ -46,9 +49,11 @@ final class RunListenerAdapter
private final RunListener runListener;
- private Optional<TestPlan> testPlan = Optional.empty();
+ private TestPlan testPlan;
- public RunListenerAdapter( RunListener runListener )
+ private Set<TestIdentifier> testSetNodes = ConcurrentHashMap.newKeySet();
+
+ RunListenerAdapter( RunListener runListener )
{
this.runListener = runListener;
}
@@ -56,78 +61,203 @@ final class RunListenerAdapter
@Override
public void testPlanExecutionStarted( TestPlan testPlan )
{
- this.testPlan = Optional.of( testPlan );
+ updateTestPlan( testPlan );
}
@Override
public void testPlanExecutionFinished( TestPlan testPlan )
{
- this.testPlan = Optional.empty();
+ updateTestPlan( null );
}
@Override
public void executionStarted( TestIdentifier testIdentifier )
{
+ if ( testIdentifier.isContainer()
+ && testIdentifier.getSource().filter( ClassSource.class::isInstance ).isPresent() )
+ {
+ startTestSetIfPossible( testIdentifier );
+ }
if ( testIdentifier.isTest() )
{
- runListener.testStarting( createReportEntry( testIdentifier, Optional.empty() ) );
+ ensureTestSetStarted( testIdentifier );
+ runListener.testStarting( createReportEntry( testIdentifier ) );
}
}
@Override
public void executionSkipped( TestIdentifier testIdentifier, String reason )
{
- String source = getClassName( testIdentifier ).orElseGet( () -> parentDisplayName( testIdentifier ) );
- runListener.testSkipped( ignored( source, testIdentifier.getDisplayName(), reason ) );
+ ensureTestSetStarted( testIdentifier );
+ String source = getLegacyReportingClassName( testIdentifier );
+ runListener.testSkipped( ignored( source, getLegacyReportingName( testIdentifier ), reason ) );
+ completeTestSetIfNecessary( testIdentifier );
}
@Override
- public void executionFinished( TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ public void executionFinished(
+ TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
{
if ( testExecutionResult.getStatus() == ABORTED )
{
- runListener.testAssumptionFailure( createReportEntry( testIdentifier,
- testExecutionResult.getThrowable() ) );
+ runListener.testAssumptionFailure( createReportEntry( testIdentifier, testExecutionResult ) );
}
else if ( testExecutionResult.getStatus() == FAILED )
{
- runListener.testFailed( createReportEntry( testIdentifier, testExecutionResult.getThrowable() ) );
+ reportFailedTest( testIdentifier, testExecutionResult );
}
else if ( testIdentifier.isTest() )
{
- runListener.testSucceeded( createReportEntry( testIdentifier, Optional.empty() ) );
+ runListener.testSucceeded( createReportEntry( testIdentifier ) );
}
+ completeTestSetIfNecessary( testIdentifier );
}
- private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier, Optional<Throwable> throwable )
+ private void updateTestPlan( TestPlan testPlan )
{
- Optional<String> className = getClassName( testIdentifier );
- if ( className.isPresent() )
+ this.testPlan = testPlan;
+ testSetNodes.clear();
+ }
+
+ private void ensureTestSetStarted( TestIdentifier testIdentifier )
+ {
+ if ( isTestSetStarted( testIdentifier ) )
+ {
+ return;
+ }
+ if ( testIdentifier.isTest() )
{
- StackTraceWriter traceWriter = new PojoStackTraceWriter( className.get(),
- getMethodName( testIdentifier ).orElse( "" ), throwable.orElse( null ) );
- return new SimpleReportEntry( className.get(), testIdentifier.getDisplayName(), traceWriter,
- (Integer) null );
+ startTestSet( testPlan.getParent( testIdentifier ).orElse( testIdentifier ) );
}
else
{
- return new SimpleReportEntry( parentDisplayName( testIdentifier ), testIdentifier.getDisplayName(),
- (Integer) null );
+ startTestSet( testIdentifier );
+ }
+ }
+
+ private boolean isTestSetStarted( TestIdentifier testIdentifier )
+ {
+ return testSetNodes.contains( testIdentifier )
+ || testPlan.getParent( testIdentifier ).map( this::isTestSetStarted ).orElse( false );
+ }
+
+ private void startTestSetIfPossible( TestIdentifier testIdentifier )
+ {
+ if ( !isTestSetStarted( testIdentifier ) )
+ {
+ startTestSet( testIdentifier );
}
}
- private Optional<String> getClassName( TestIdentifier testIdentifier )
+ private void completeTestSetIfNecessary( TestIdentifier testIdentifier )
+ {
+ if ( testSetNodes.contains( testIdentifier ) )
+ {
+ completeTestSet( testIdentifier );
+ }
+ }
+
+ private void startTestSet( TestIdentifier testIdentifier )
+ {
+ runListener.testSetStarting( createTestSetReportEntry( testIdentifier ) );
+ testSetNodes.add( testIdentifier );
+ }
+
+ private void completeTestSet( TestIdentifier testIdentifier )
+ {
+ runListener.testSetCompleted( createTestSetReportEntry( testIdentifier ) );
+ testSetNodes.remove( testIdentifier );
+ }
+
+ private void reportFailedTest(
+ TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ {
+ SimpleReportEntry reportEntry = createReportEntry( testIdentifier, testExecutionResult );
+ if ( testExecutionResult.getThrowable().filter( AssertionError.class::isInstance ).isPresent() )
+ {
+ runListener.testFailed( reportEntry );
+ }
+ else
+ {
+ runListener.testError( reportEntry );
+ }
+ }
+
+ private SimpleReportEntry createTestSetReportEntry( TestIdentifier testIdentifier )
+ {
+ return new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(), testIdentifier.getLegacyReportingName() );
+ }
+
+ private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier )
+ {
+ return createReportEntry( testIdentifier, (StackTraceWriter) null );
+ }
+
+ private SimpleReportEntry createReportEntry(
+ TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ {
+ return createReportEntry(
+ testIdentifier, getStackTraceWriter( testIdentifier, testExecutionResult ) );
+ }
+
+ private SimpleReportEntry createReportEntry(
+ TestIdentifier testIdentifier, StackTraceWriter stackTraceWriter )
+ {
+ String source = getLegacyReportingClassName( testIdentifier );
+ String name = getLegacyReportingName( testIdentifier );
+
+ return SimpleReportEntry.withException( source, name, stackTraceWriter );
+ }
+
+ private String getLegacyReportingName( TestIdentifier testIdentifier )
+ {
+ // Surefire cuts off the name at the first '(' character. Thus, we have to pick a different
+ // character to represent parentheses. "()" are removed entirely to maximize compatibility with
+ // existing reporting tools because in the old days test methods used to not have parameters.
+ return testIdentifier
+ .getLegacyReportingName()
+ .replace( "()", "" )
+ .replace( '(', '{' )
+ .replace( ')', '}' );
+ }
+
+ private String getLegacyReportingClassName( TestIdentifier testIdentifier )
+ {
+ return LegacyReportingUtils.getClassName( testPlan, testIdentifier );
+ }
+
+ private StackTraceWriter getStackTraceWriter(
+ TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ {
+ Optional<Throwable> throwable = testExecutionResult.getThrowable();
+ if ( testExecutionResult.getStatus() == FAILED )
+ {
+ // Failed tests must have a StackTraceWriter, otherwise Surefire will fail
+ return getStackTraceWriter( testIdentifier, throwable.orElse( null ) );
+ }
+ return throwable.map( t -> getStackTraceWriter( testIdentifier, t ) ).orElse( null );
+ }
+
+ private StackTraceWriter getStackTraceWriter( TestIdentifier testIdentifier, Throwable throwable )
+ {
+ String className = getClassName( testIdentifier );
+ String methodName = getMethodName( testIdentifier ).orElse( "" );
+ return new PojoStackTraceWriter( className, methodName, throwable );
+ }
+
+ private String getClassName( TestIdentifier testIdentifier )
{
TestSource testSource = testIdentifier.getSource().orElse( null );
if ( testSource instanceof ClassSource )
{
- return Optional.of( ( (ClassSource) testSource ).getJavaClass().getName() );
+ return ( (ClassSource) testSource ).getJavaClass().getName();
}
if ( testSource instanceof MethodSource )
{
- return Optional.of( ( (MethodSource) testSource ).getClassName() );
+ return ( (MethodSource) testSource ).getClassName();
}
- return Optional.empty();
+ return testPlan.getParent( testIdentifier ).map( this::getClassName ).orElse( "" );
}
private Optional<String> getMethodName( TestIdentifier testIdentifier )
@@ -139,12 +269,4 @@ final class RunListenerAdapter
}
return Optional.empty();
}
-
- private String parentDisplayName( TestIdentifier testIdentifier )
- {
- return testPlan
- .flatMap( plan -> plan.getParent( testIdentifier ) )
- .map( TestIdentifier::getDisplayName )
- .orElseGet( testIdentifier::getUniqueId );
- }
}
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestMethodFilter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestMethodFilter.java
new file mode 100644
index 0000000..45e32db
--- /dev/null
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestMethodFilter.java
@@ -0,0 +1,60 @@
+package org.apache.maven.surefire.junitplatform;
+
+/*
+ * 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.testset.TestListResolver;
+import org.junit.platform.engine.FilterResult;
+import org.junit.platform.engine.TestDescriptor;
+import org.junit.platform.engine.support.descriptor.MethodSource;
+import org.junit.platform.launcher.PostDiscoveryFilter;
+
+/**
+ * @since 1.0.3
+ */
+class TestMethodFilter
+ implements PostDiscoveryFilter
+{
+
+ private final TestListResolver testListResolver;
+
+ TestMethodFilter( TestListResolver testListResolver )
+ {
+ this.testListResolver = testListResolver;
+ }
+
+ @Override
+ public FilterResult apply( TestDescriptor descriptor )
+ {
+ boolean shouldRun = descriptor.getSource()
+ .filter( MethodSource.class::isInstance )
+ .map( MethodSource.class::cast )
+ .map( this::shouldRun )
+ .orElse( true );
+
+ return FilterResult.includedIf( shouldRun );
+ }
+
+ private boolean shouldRun( MethodSource source )
+ {
+ String testClass = TestListResolver.toClassFileName( source.getClassName() );
+ String testMethod = source.getMethodName();
+ return this.testListResolver.shouldRun( testClass, testMethod );
+ }
+}
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java
index 4a95d6e..4b488c1 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java
@@ -22,13 +22,10 @@ package org.apache.maven.surefire.junitplatform;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
-import java.util.function.Predicate;
-
import org.apache.maven.surefire.util.ScannerFilter;
import org.junit.platform.engine.Filter;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
-import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
/**
@@ -38,14 +35,11 @@ final class TestPlanScannerFilter
implements ScannerFilter
{
- private static final Predicate<TestIdentifier> HAS_TESTS = testIdentifier -> testIdentifier.isTest()
- || testIdentifier.isContainer();
-
private final Launcher launcher;
private final Filter<?>[] includeAndExcludeFilters;
- public TestPlanScannerFilter( Launcher launcher, Filter<?>[] includeAndExcludeFilters )
+ TestPlanScannerFilter( Launcher launcher, Filter<?>[] includeAndExcludeFilters )
{
this.launcher = launcher;
this.includeAndExcludeFilters = includeAndExcludeFilters;
@@ -55,10 +49,12 @@ final class TestPlanScannerFilter
@SuppressWarnings( "rawtypes" )
public boolean accept( Class testClass )
{
- LauncherDiscoveryRequest discoveryRequest = request().selectors( selectClass( testClass ) ).filters(
- includeAndExcludeFilters ).build();
+ LauncherDiscoveryRequest discoveryRequest = request()
+ .selectors( selectClass( testClass ) )
+ .filters( includeAndExcludeFilters ).build();
+
TestPlan testPlan = launcher.discover( discoveryRequest );
- return testPlan.countTestIdentifiers( HAS_TESTS ) > 0;
- }
+ return testPlan.containsTests();
+ }
}
diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTests.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTests.java
index a32aade..e0db97e 100644
--- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTests.java
+++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTests.java
@@ -19,24 +19,43 @@ package org.apache.maven.surefire.junitplatform;
* under the License.
*/
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
+import static java.util.stream.Collectors.toSet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.mockito.AdditionalMatchers.gt;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.maven.surefire.providerapi.ProviderParameters;
+import org.apache.maven.surefire.report.ConsoleOutputReceiver;
+import org.apache.maven.surefire.report.ReportEntry;
import org.apache.maven.surefire.report.ReporterFactory;
import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.report.SimpleReportEntry;
+import org.apache.maven.surefire.testset.TestListResolver;
+import org.apache.maven.surefire.testset.TestRequest;
+import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.RunOrderCalculator;
import org.apache.maven.surefire.util.ScanResult;
import org.apache.maven.surefire.util.TestsToRun;
@@ -44,10 +63,14 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.util.PreconditionViolationException;
import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
+import org.junit.platform.launcher.listeners.TestExecutionSummary.Failure;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
/**
* Unit tests for {@link JUnitPlatformProvider}.
@@ -59,9 +82,10 @@ class JUnitPlatformProviderTests
@Test
void getSuitesReturnsScannedClasses()
- throws Exception
+ throws Exception
{
- ProviderParameters providerParameters = providerParametersMock( TestClass1.class, TestClass2.class );
+ ProviderParameters providerParameters =
+ providerParametersMock( TestClass1.class, TestClass2.class );
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
assertThat( provider.getSuites() ).containsOnly( TestClass1.class, TestClass2.class );
@@ -69,17 +93,18 @@ class JUnitPlatformProviderTests
@Test
void invokeThrowsForWrongForkTestSet()
- throws Exception
+ throws Exception
{
ProviderParameters providerParameters = providerParametersMock( Integer.class );
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
- assertThrows( IllegalArgumentException.class, () -> provider.invoke( "wrong forkTestSet" ) );
+ assertThrows(
+ IllegalArgumentException.class, () -> invokeProvider( provider, "wrong forkTestSet" ) );
}
@Test
void allGivenTestsToRunAreInvoked()
- throws Exception
+ throws Exception
{
Launcher launcher = LauncherFactory.create();
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParametersMock(), launcher );
@@ -88,16 +113,25 @@ class JUnitPlatformProviderTests
launcher.registerTestExecutionListeners( executionListener );
TestsToRun testsToRun = newTestsToRun( TestClass1.class, TestClass2.class );
- provider.invoke( testsToRun );
+ invokeProvider( provider, testsToRun );
- assertThat( executionListener.summaries ).hasSize( 2 );
- TestClass1.verifyExecutionSummary( executionListener.summaries.get( 0 ) );
- TestClass2.verifyExecutionSummary( executionListener.summaries.get( 1 ) );
+ assertThat( executionListener.summaries ).hasSize( 1 );
+ TestExecutionSummary summary = executionListener.summaries.get( 0 );
+ assertEquals( TestClass1.TESTS_FOUND + TestClass2.TESTS_FOUND, summary.getTestsFoundCount() );
+ assertEquals(
+ TestClass1.TESTS_STARTED + TestClass2.TESTS_STARTED, summary.getTestsStartedCount() );
+ assertEquals(
+ TestClass1.TESTS_SKIPPED + TestClass2.TESTS_SKIPPED, summary.getTestsSkippedCount() );
+ assertEquals(
+ TestClass1.TESTS_SUCCEEDED + TestClass2.TESTS_SUCCEEDED, summary.getTestsSucceededCount() );
+ assertEquals(
+ TestClass1.TESTS_ABORTED + TestClass2.TESTS_ABORTED, summary.getTestsAbortedCount() );
+ assertEquals( TestClass1.TESTS_FAILED + TestClass2.TESTS_FAILED, summary.getTestsFailedCount() );
}
@Test
void singleTestClassIsInvoked()
- throws Exception
+ throws Exception
{
Launcher launcher = LauncherFactory.create();
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParametersMock(), launcher );
@@ -105,28 +139,94 @@ class JUnitPlatformProviderTests
TestPlanSummaryListener executionListener = new TestPlanSummaryListener();
launcher.registerTestExecutionListeners( executionListener );
- provider.invoke( TestClass1.class );
+ invokeProvider( provider, TestClass1.class );
assertThat( executionListener.summaries ).hasSize( 1 );
- TestClass1.verifyExecutionSummary( executionListener.summaries.get( 0 ) );
+ TestExecutionSummary summary = executionListener.summaries.get( 0 );
+ assertEquals( TestClass1.TESTS_FOUND, summary.getTestsFoundCount() );
+ assertEquals( TestClass1.TESTS_STARTED, summary.getTestsStartedCount() );
+ assertEquals( TestClass1.TESTS_SKIPPED, summary.getTestsSkippedCount() );
+ assertEquals( TestClass1.TESTS_SUCCEEDED, summary.getTestsSucceededCount() );
+ assertEquals( TestClass1.TESTS_ABORTED, summary.getTestsAbortedCount() );
+ assertEquals( TestClass1.TESTS_FAILED, summary.getTestsFailedCount() );
}
@Test
void allDiscoveredTestsAreInvokedForNullArgument()
- throws Exception
+ throws Exception
{
- ProviderParameters providerParameters = providerParametersMock( TestClass1.class, TestClass2.class );
+ RunListener runListener = runListenerMock();
+ ProviderParameters providerParameters =
+ providerParametersMock( runListener, TestClass1.class, TestClass2.class );
Launcher launcher = LauncherFactory.create();
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters, launcher );
TestPlanSummaryListener executionListener = new TestPlanSummaryListener();
launcher.registerTestExecutionListeners( executionListener );
- provider.invoke( null );
+ invokeProvider( provider, null );
+
+ InOrder inOrder = inOrder( runListener );
+ inOrder
+ .verify( runListener )
+ .testSetStarting(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ TestClass1.class.getName() ) );
+ inOrder
+ .verify( runListener )
+ .testSetCompleted(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ TestClass1.class.getName() ) );
+ inOrder
+ .verify( runListener )
+ .testSetStarting(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ TestClass2.class.getName() ) );
+ inOrder
+ .verify( runListener )
+ .testSetCompleted(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ TestClass2.class.getName() ) );
+
+ assertThat( executionListener.summaries ).hasSize( 1 );
+ TestExecutionSummary summary = executionListener.summaries.get( 0 );
+ assertEquals( TestClass1.TESTS_FOUND + TestClass2.TESTS_FOUND, summary.getTestsFoundCount() );
+ assertEquals(
+ TestClass1.TESTS_STARTED + TestClass2.TESTS_STARTED, summary.getTestsStartedCount() );
+ assertEquals(
+ TestClass1.TESTS_SKIPPED + TestClass2.TESTS_SKIPPED, summary.getTestsSkippedCount() );
+ assertEquals(
+ TestClass1.TESTS_SUCCEEDED + TestClass2.TESTS_SUCCEEDED, summary.getTestsSucceededCount() );
+ assertEquals(
+ TestClass1.TESTS_ABORTED + TestClass2.TESTS_ABORTED, summary.getTestsAbortedCount() );
+ assertEquals( TestClass1.TESTS_FAILED + TestClass2.TESTS_FAILED, summary.getTestsFailedCount() );
+ }
- assertThat( executionListener.summaries ).hasSize( 2 );
- TestClass1.verifyExecutionSummary( executionListener.summaries.get( 0 ) );
- TestClass2.verifyExecutionSummary( executionListener.summaries.get( 1 ) );
+ @Test
+ void outputIsCaptured()
+ throws Exception
+ {
+ Launcher launcher = LauncherFactory.create();
+ RunListener runListener = runListenerMock();
+ JUnitPlatformProvider provider =
+ new JUnitPlatformProvider( providerParametersMock( runListener ), launcher );
+
+ invokeProvider( provider, VerboseTestClass.class );
+
+ ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass( byte[].class );
+ // @formatter:off
+ verify( (ConsoleOutputReceiver) runListener )
+ .writeTestOutput( captor.capture(), eq( 0 ), gt( 6 ), eq( true ) );
+ verify( (ConsoleOutputReceiver) runListener )
+ .writeTestOutput( captor.capture(), eq( 0 ), gt( 6 ), eq( false ) );
+ assertThat( captor.getAllValues() )
+ .extracting( bytes -> new String( bytes, 0, 6 ) )
+ .containsExactly( "stdout", "stderr" );
+ // @formatter:on
}
@Test
@@ -139,16 +239,17 @@ class JUnitPlatformProviderTests
}
@Test
- void bothExcludedGroupsAndExcludeTagsThrowsException() {
+ void bothExcludedGroupsAndExcludeTagsThrowsException()
+ {
Map<String, String> properties = new HashMap<>();
- properties.put(JUnitPlatformProvider.EXCLUDE_GROUPS, "groupOne, groupTwo");
- properties.put(JUnitPlatformProvider.EXCLUDE_TAGS, "tagOne, tagTwo");
- verifyPreconditionViolationException(properties);
+ properties.put( JUnitPlatformProvider.EXCLUDE_GROUPS, "groupOne, groupTwo" );
+ properties.put( JUnitPlatformProvider.EXCLUDE_TAGS, "tagOne, tagTwo" );
+ verifyPreconditionViolationException( properties );
}
@Test
void onlyGroupsIsDeclared()
- throws Exception
+ throws Exception
{
Map<String, String> properties = new HashMap<>();
properties.put( JUnitPlatformProvider.INCLUDE_GROUPS, "groupOne, groupTwo" );
@@ -158,12 +259,12 @@ class JUnitPlatformProviderTests
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
- assertEquals( 1, provider.includeAndExcludeFilters.length );
+ assertEquals( 1, provider.filters.length );
}
@Test
void onlyExcludeTagsIsDeclared()
- throws Exception
+ throws Exception
{
Map<String, String> properties = new HashMap<>();
properties.put( JUnitPlatformProvider.EXCLUDE_TAGS, "tagOne, tagTwo" );
@@ -173,12 +274,44 @@ class JUnitPlatformProviderTests
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
- assertEquals( 1, provider.includeAndExcludeFilters.length );
+ assertEquals( 1, provider.filters.length );
+ }
+
+ @Test
+ void noFiltersAreCreatedIfTagsAreEmpty()
+ throws Exception
+ {
+ Map<String, String> properties = new HashMap<>();
+ properties.put( JUnitPlatformProvider.INCLUDE_TAGS, "" );
+ properties.put( JUnitPlatformProvider.INCLUDE_GROUPS, "" );
+
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() ).thenReturn( properties );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+ assertEquals( 0, provider.filters.length );
+ }
+
+ @Test
+ void filtersWithEmptyTagsAreNotRegistered()
+ throws Exception
+ {
+ Map<String, String> properties = new HashMap<>();
+
+ // Here only tagOne is registered as a valid tag and other tags are ignored as they are empty
+ properties.put( JUnitPlatformProvider.EXCLUDE_GROUPS, "tagOne," );
+ properties.put( JUnitPlatformProvider.EXCLUDE_TAGS, "" );
+
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() ).thenReturn( properties );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+ assertEquals( 1, provider.filters.length );
}
@Test
void bothIncludeAndExcludeAreAllowed()
- throws Exception
+ throws Exception
{
Map<String, String> properties = new HashMap<>();
properties.put( JUnitPlatformProvider.INCLUDE_TAGS, "tagOne, tagTwo" );
@@ -189,18 +322,173 @@ class JUnitPlatformProviderTests
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
- assertEquals( 2, provider.includeAndExcludeFilters.length );
+ assertEquals( 2, provider.filters.length );
+ }
+
+ @Test
+ void tagExpressionsAreSupportedForIncludeTagsContainingVerticalBar()
+ {
+ Map<String, String> properties = new HashMap<>();
+ properties.put( JUnitPlatformProvider.INCLUDE_TAGS, "tagOne | tagTwo" );
+ properties.put( JUnitPlatformProvider.EXCLUDE_TAGS, "tagThree | tagFour" );
+
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() ).thenReturn( properties );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+
+ assertEquals( 2, provider.filters.length );
+ }
+
+ @Test
+ void tagExpressionsAreSupportedForIncludeTagsContainingAmpersand()
+ {
+ Map<String, String> properties = new HashMap<>();
+ properties.put( JUnitPlatformProvider.INCLUDE_TAGS, "tagOne & !tagTwo" );
+ properties.put( JUnitPlatformProvider.EXCLUDE_TAGS, "tagThree & !tagFour" );
+
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() ).thenReturn( properties );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+
+ assertEquals( 2, provider.filters.length );
}
@Test
void noFiltersAreCreatedIfNoPropertiesAreDeclared()
- throws Exception
+ throws Exception
+ {
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+
+ assertEquals( 0, provider.filters.length );
+ }
+
+ @Test
+ void defaultConfigurationParametersAreEmpty()
{
ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() ).thenReturn( emptyMap() );
JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
- assertEquals( 0, provider.includeAndExcludeFilters.length );
+ assertTrue( provider.configurationParameters.isEmpty() );
+ }
+
+ @Test
+ void parsesConfigurationParameters()
+ {
+ ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
+ when( providerParameters.getProviderProperties() )
+ .thenReturn( //
+ singletonMap(
+ JUnitPlatformProvider.CONFIGURATION_PARAMETERS,
+ "foo = true\nbar 42\rbaz: *\r\nqux: EOF" ) );
+
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters );
+
+ assertEquals( 4, provider.configurationParameters.size() );
+ assertEquals( "true", provider.configurationParameters.get( "foo" ) );
+ assertEquals( "42", provider.configurationParameters.get( "bar" ) );
+ assertEquals( "*", provider.configurationParameters.get( "baz" ) );
+ assertEquals( "EOF", provider.configurationParameters.get( "qux" ) );
+ }
+
+ @Test
+ void executesSingleTestIncludedByName()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=TestClass3#prefix1Suffix1'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "*TestClass3#prefix1Suffix1";
+
+ testExecutionOfMatchingTestMethods( TestClass3.class, pattern, "prefix1Suffix1()" );
+ }
+
+ @Test
+ void executesMultipleTestsIncludedByName()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=TestClass3#prefix1Suffix1+prefix2Suffix1'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "*TestClass3#prefix1Suffix1+prefix2Suffix1";
+
+ testExecutionOfMatchingTestMethods(
+ TestClass3.class, pattern, "prefix1Suffix1()", "prefix2Suffix1()" );
+ }
+
+ @Test
+ void executesMultipleTestsIncludedByNamePattern()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=TestClass3#prefix1*'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "*TestClass3#prefix1*";
+
+ testExecutionOfMatchingTestMethods(
+ TestClass3.class, pattern, "prefix1Suffix1()", "prefix1Suffix2()" );
+ }
+
+ @Test
+ void executesMultipleTestsIncludedByNamePatternWithQuestionMark()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=TestClass3#prefix?Suffix2'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "*TestClass3#prefix?Suffix2";
+
+ testExecutionOfMatchingTestMethods(
+ TestClass3.class, pattern, "prefix1Suffix2()", "prefix2Suffix2()" );
+ }
+
+ @Test
+ void doesNotExecuteTestsExcludedByName()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=!TestClass3#prefix1Suffix2'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "!*TestClass3#prefix1Suffix2";
+
+ testExecutionOfMatchingTestMethods(
+ TestClass3.class, pattern, "prefix1Suffix1()", "prefix2Suffix1()", "prefix2Suffix2()" );
+ }
+
+ @Test
+ void doesNotExecuteTestsExcludedByNamePattern()
+ throws Exception
+ {
+ // following is equivalent of adding '-Dtest=!TestClass3#prefix2*'
+ // '*' needed because it's a nested class and thus has name prefixed with '$'
+ String pattern = "!*TestClass3#prefix2*";
+
+ testExecutionOfMatchingTestMethods(
+ TestClass3.class, pattern, "prefix1Suffix1()", "prefix1Suffix2()" );
+ }
+
+ void testExecutionOfMatchingTestMethods(
+ Class<?> testClass, String pattern, String... expectedTestNames )
+ throws Exception
+ {
+ TestListResolver testListResolver = new TestListResolver( pattern );
+ ProviderParameters providerParameters = providerParametersMock( testListResolver, testClass );
+ Launcher launcher = LauncherFactory.create();
+ JUnitPlatformProvider provider = new JUnitPlatformProvider( providerParameters, launcher );
+
+ TestPlanSummaryListener executionListener = new TestPlanSummaryListener();
+ launcher.registerTestExecutionListeners( executionListener );
+
+ invokeProvider( provider, null );
+
+ assertEquals( 1, executionListener.summaries.size() );
+ TestExecutionSummary summary = executionListener.summaries.get( 0 );
+ int expectedCount = expectedTestNames.length;
+ assertEquals( expectedCount, summary.getTestsFoundCount() );
+ assertEquals( expectedCount, summary.getTestsFailedCount() );
+ assertEquals( expectedCount, summary.getFailures().size() );
+
+ assertThat( failedTestDisplayNames( summary ) ).contains( expectedTestNames );
}
private void verifyPreconditionViolationException( Map<String, String> properties )
@@ -208,14 +496,35 @@ class JUnitPlatformProviderTests
ProviderParameters providerParameters = providerParametersMock( TestClass1.class );
when( providerParameters.getProviderProperties() ).thenReturn( properties );
- Throwable throwable = assertThrows( PreconditionViolationException.class, () ->
- new JUnitPlatformProvider(providerParameters) );
+ Throwable throwable =
+ assertThrows(
+ PreconditionViolationException.class,
+ () -> new JUnitPlatformProvider( providerParameters ) );
assertEquals( JUnitPlatformProvider.EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED, throwable.getMessage() );
}
private static ProviderParameters providerParametersMock( Class<?>... testClasses )
{
+ return providerParametersMock( runListenerMock(), testClasses );
+ }
+
+ private static ProviderParameters providerParametersMock(
+ RunListener runListener, Class<?>... testClasses )
+ {
+ TestListResolver testListResolver = new TestListResolver( "" );
+ return providerParametersMock( runListener, testListResolver, testClasses );
+ }
+
+ private static ProviderParameters providerParametersMock(
+ TestListResolver testListResolver, Class<?>... testClasses )
+ {
+ return providerParametersMock( runListenerMock(), testListResolver, testClasses );
+ }
+
+ private static ProviderParameters providerParametersMock(
+ RunListener runListener, TestListResolver testListResolver, Class<?>... testClasses )
+ {
TestsToRun testsToRun = newTestsToRun( testClasses );
ScanResult scanResult = mock( ScanResult.class );
@@ -225,17 +534,37 @@ class JUnitPlatformProviderTests
when( runOrderCalculator.orderTestClasses( any() ) ).thenReturn( testsToRun );
ReporterFactory reporterFactory = mock( ReporterFactory.class );
- RunListener runListener = mock( RunListener.class );
when( reporterFactory.createReporter() ).thenReturn( runListener );
+ TestRequest testRequest = mock( TestRequest.class );
+ when( testRequest.getTestListResolver() ).thenReturn( testListResolver );
+
ProviderParameters providerParameters = mock( ProviderParameters.class );
when( providerParameters.getScanResult() ).thenReturn( scanResult );
when( providerParameters.getRunOrderCalculator() ).thenReturn( runOrderCalculator );
when( providerParameters.getReporterFactory() ).thenReturn( reporterFactory );
+ when( providerParameters.getTestRequest() ).thenReturn( testRequest );
return providerParameters;
}
+ private static RunListener runListenerMock()
+ {
+ return mock( RunListener.class, withSettings().extraInterfaces( ConsoleOutputReceiver.class ) );
+ }
+
+ private static Set<String> failedTestDisplayNames( TestExecutionSummary summary )
+ {
+ // @formatter:off
+ return summary
+ .getFailures()
+ .stream()
+ .map( Failure::getTestIdentifier )
+ .map( TestIdentifier::getDisplayName )
+ .collect( toSet() );
+ // @formatter:on
+ }
+
private static TestsToRun newTestsToRun( Class<?>... testClasses )
{
List<Class<?>> classesList = Arrays.asList( testClasses );
@@ -243,7 +572,7 @@ class JUnitPlatformProviderTests
}
private class TestPlanSummaryListener
- extends SummaryGeneratingListener
+ extends SummaryGeneratingListener
{
final List<TestExecutionSummary> summaries = new ArrayList<>();
@@ -256,9 +585,42 @@ class JUnitPlatformProviderTests
}
}
- private static class TestClass1
+ /**
+ * Invokes the provider, then restores system out and system error.
+ *
+ * @see <a href="https://github.com/junit-team/junit5/issues/986">#986</a>
+ */
+ private void invokeProvider( JUnitPlatformProvider provider, Object forkTestSet )
+ throws TestSetFailedException, InvocationTargetException
+ {
+ PrintStream systemOut = System.out;
+ PrintStream systemErr = System.err;
+ try
+ {
+ provider.invoke( forkTestSet );
+ }
+ finally
+ {
+ System.setOut( systemOut );
+ System.setErr( systemErr );
+ }
+ }
+
+ static class TestClass1
{
+ static final int TESTS_FOUND = 4;
+
+ static final int TESTS_STARTED = 3;
+
+ static final int TESTS_SKIPPED = 1;
+
+ static final int TESTS_SUCCEEDED = 2;
+
+ static final int TESTS_ABORTED = 0;
+
+ static final int TESTS_FAILED = 1;
+
@Test
void test1()
{
@@ -280,21 +642,23 @@ class JUnitPlatformProviderTests
{
throw new RuntimeException();
}
-
- static void verifyExecutionSummary( TestExecutionSummary summary )
- {
- assertEquals( 4, summary.getTestsFoundCount() );
- assertEquals( 3, summary.getTestsStartedCount() );
- assertEquals( 2, summary.getTestsSucceededCount() );
- assertEquals( 1, summary.getTestsSkippedCount() );
- assertEquals( 0, summary.getTestsAbortedCount() );
- assertEquals( 1, summary.getTestsFailedCount() );
- }
}
- private static class TestClass2
+ static class TestClass2
{
+ static final int TESTS_FOUND = 3;
+
+ static final int TESTS_STARTED = 3;
+
+ static final int TESTS_SKIPPED = 0;
+
+ static final int TESTS_SUCCEEDED = 1;
+
+ static final int TESTS_ABORTED = 1;
+
+ static final int TESTS_FAILED = 1;
+
@Test
void test1()
{
@@ -311,15 +675,82 @@ class JUnitPlatformProviderTests
{
assumeTrue( false );
}
+ }
+
+ static class VerboseTestClass
+ {
+ @Test
+ void test()
+ {
+ System.out.println( "stdout" );
+ System.err.println( "stderr" );
+ }
+ }
+
+ @Test
+ void usesClassNamesForXmlReport()
+ throws TestSetFailedException, InvocationTargetException
+ {
+ String[] classNames = { Sub1Tests.class.getName(), Sub2Tests.class.getName() };
+ ProviderParameters providerParameters =
+ providerParametersMock( Sub1Tests.class, Sub2Tests.class );
+
+ JUnitPlatformProvider jUnitPlatformProvider = new JUnitPlatformProvider( providerParameters );
+ TestsToRun testsToRun = newTestsToRun( Sub1Tests.class, Sub2Tests.class );
+
+ invokeProvider( jUnitPlatformProvider, testsToRun );
+ RunListener reporter = providerParameters.getReporterFactory().createReporter();
+
+ ArgumentCaptor<ReportEntry> reportEntryArgumentCaptor =
+ ArgumentCaptor.forClass( ReportEntry.class );
+ verify( reporter, times( 2 ) ).testSucceeded( reportEntryArgumentCaptor.capture() );
+
+ List<ReportEntry> allValues = reportEntryArgumentCaptor.getAllValues();
+ assertThat( allValues ).extracting( ReportEntry::getSourceName ).containsExactly( classNames );
+ }
+
+ static class AbstractTestClass
+ {
+ @Test
+ void test()
+ {
+ }
+ }
+
+ static class Sub1Tests
+ extends AbstractTestClass
+ {
+ }
+
+ static class Sub2Tests
+ extends AbstractTestClass
+ {
+ }
+
+ static class TestClass3
+ {
+ @Test
+ void prefix1Suffix1()
+ {
+ throw new RuntimeException();
+ }
- static void verifyExecutionSummary( TestExecutionSummary summary )
+ @Test
+ void prefix2Suffix1()
+ {
+ throw new RuntimeException();
+ }
+
+ @Test
+ void prefix1Suffix2()
{
- assertEquals( 3, summary.getTestsFoundCount() );
- assertEquals( 3, summary.getTestsStartedCount() );
- assertEquals( 1, summary.getTestsSucceededCount() );
- assertEquals( 0, summary.getTestsSkippedCount() );
- assertEquals( 1, summary.getTestsAbortedCount() );
- assertEquals( 1, summary.getTestsFailedCount() );
+ throw new RuntimeException();
+ }
+
+ @Test
+ void prefix2Suffix2()
+ {
+ throw new RuntimeException();
}
}
}
diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTests.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTests.java
index 0a37eb5..d3ec7a4 100644
--- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTests.java
+++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTests.java
@@ -19,31 +19,45 @@ package org.apache.maven.surefire.junitplatform;
* under the License.
*/
-import static java.util.Collections.singletonList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singleton;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.platform.engine.TestExecutionResult.successful;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import java.util.Collections;
import java.util.Optional;
import org.apache.maven.surefire.report.ReportEntry;
import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.report.SimpleReportEntry;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.engine.descriptor.ClassTestDescriptor;
import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor;
import org.junit.platform.engine.TestDescriptor;
+import org.junit.platform.engine.TestDescriptor.Type;
import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.TestSource;
import org.junit.platform.engine.UniqueId;
+import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor;
+import org.junit.platform.engine.support.descriptor.ClassSource;
import org.junit.platform.engine.support.descriptor.EngineDescriptor;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
/**
* Unit tests for {@link RunListenerAdapter}.
@@ -52,7 +66,9 @@ import org.mockito.ArgumentCaptor;
*/
class RunListenerAdapterTests
{
+
private RunListener listener;
+
private RunListenerAdapter adapter;
@BeforeEach
@@ -60,32 +76,183 @@ class RunListenerAdapterTests
{
listener = mock( RunListener.class );
adapter = new RunListenerAdapter( listener );
+ adapter.testPlanExecutionStarted( TestPlan.from( emptyList() ) );
}
@Test
void notifiedWithCorrectNamesWhenMethodExecutionStarted()
- throws Exception
+ throws Exception
{
ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
- adapter.executionStarted( newMethodIdentifier() );
+ TestPlan testPlan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
+ adapter.testPlanExecutionStarted( testPlan );
+
+ TestIdentifier methodIdentifier =
+ identifiersAsParentOnTestPlan( testPlan, newClassDescriptor(), newMethodDescriptor() );
+
+ adapter.executionStarted( methodIdentifier );
verify( listener ).testStarting( entryCaptor.capture() );
ReportEntry entry = entryCaptor.getValue();
- assertEquals( MY_TEST_METHOD_NAME + "()", entry.getName() );
+ assertEquals( MY_TEST_METHOD_NAME, entry.getName() );
assertEquals( MyTestClass.class.getName(), entry.getSourceName() );
- assertNotNull( entry.getStackTraceWriter() );
+ assertNull( entry.getStackTraceWriter() );
}
@Test
- void notNotifiedWhenClassExecutionStarted()
+ void notifiedWithCompatibleNameForMethodWithArguments()
+ throws Exception
{
- adapter.executionStarted( newClassIdentifier() );
- verify( listener, never() ).testStarting( any() );
+ ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+
+ TestPlan testPlan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
+ adapter.testPlanExecutionStarted( testPlan );
+
+ TestIdentifier methodIdentifier =
+ identifiersAsParentOnTestPlan(
+ testPlan, newClassDescriptor(), newMethodDescriptor( String.class ) );
+
+ adapter.executionStarted( methodIdentifier );
+ verify( listener ).testStarting( entryCaptor.capture() );
+
+ ReportEntry entry = entryCaptor.getValue();
+ assertEquals( MY_TEST_METHOD_NAME + "{String}", entry.getName() );
+ assertEquals( MyTestClass.class.getName(), entry.getSourceName() );
+ assertNull( entry.getStackTraceWriter() );
+ }
+
+ @Test
+ void notifiedEagerlyForTestSetWhenClassExecutionStarted()
+ throws Exception
+ {
+ EngineDescriptor engine = newEngineDescriptor();
+ TestDescriptor parent = newClassDescriptor();
+ engine.addChild( parent );
+ TestDescriptor child = newMethodDescriptor();
+ parent.addChild( child );
+ TestPlan plan = TestPlan.from( Collections.singletonList( engine ) );
+
+ adapter.testPlanExecutionStarted( plan );
+ adapter.executionStarted( TestIdentifier.from( engine ) );
+ adapter.executionStarted( TestIdentifier.from( parent ) );
+ verify( listener )
+ .testSetStarting(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ MyTestClass.class.getName() ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionStarted( TestIdentifier.from( child ) );
+ verify( listener )
+ .testStarting( new SimpleReportEntry( MyTestClass.class.getName(), MY_TEST_METHOD_NAME ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( child ), successful() );
+ verify( listener )
+ .testSucceeded( new SimpleReportEntry( MyTestClass.class.getName(), MY_TEST_METHOD_NAME ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( parent ), successful() );
+ verify( listener )
+ .testSetCompleted(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ MyTestClass.class.getName() ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( engine ), successful() );
+ verifyNoMoreInteractions( listener );
+ }
+
+ @Test
+ void notifiedLazilyForTestSetWhenFirstTestWithoutClassDescriptorParentStarted()
+ {
+ EngineDescriptor engine = newEngineDescriptor();
+ TestDescriptor parent =
+ newTestDescriptor(
+ engine.getUniqueId().append( "container", "noClass" ), "parent",
+ Type.CONTAINER );
+ engine.addChild( parent );
+ TestDescriptor child1 =
+ newTestDescriptor( parent.getUniqueId().append( "test", "child1" ), "child1", Type.TEST );
+ parent.addChild( child1 );
+ TestDescriptor child2 =
+ newTestDescriptor( parent.getUniqueId().append( "test", "child2" ), "child2", Type.TEST );
+ parent.addChild( child2 );
+ TestPlan plan = TestPlan.from( Collections.singletonList( engine ) );
+
+ adapter.testPlanExecutionStarted( plan );
+ adapter.executionStarted( TestIdentifier.from( engine ) );
+ adapter.executionStarted( TestIdentifier.from( parent ) );
+ verifyZeroInteractions( listener );
+
+ adapter.executionStarted( TestIdentifier.from( child1 ) );
+ InOrder inOrder = inOrder( listener );
+ inOrder
+ .verify( listener )
+ .testSetStarting( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "parent" ) );
+ inOrder.verify( listener ).testStarting( new SimpleReportEntry( "parent", "child1" ) );
+ inOrder.verifyNoMoreInteractions();
+
+ adapter.executionFinished( TestIdentifier.from( child1 ), successful() );
+ verify( listener ).testSucceeded( new SimpleReportEntry( "parent", "child1" ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionStarted( TestIdentifier.from( child2 ) );
+ verify( listener ).testStarting( new SimpleReportEntry( "parent", "child2" ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( child2 ), successful() );
+ verify( listener ).testSucceeded( new SimpleReportEntry( "parent", "child2" ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( parent ), successful() );
+ verify( listener )
+ .testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "parent" ) );
+ verifyNoMoreInteractions( listener );
+
+ adapter.executionFinished( TestIdentifier.from( engine ), successful() );
+ verifyNoMoreInteractions( listener );
+ }
+
+ @Test
+ void notifiedForTestSetForSingleNodeEngine()
+ {
+ EngineDescriptor engine =
+ new EngineDescriptor( UniqueId.forEngine( "engine" ), "engine" )
+ {
+ @Override
+ public Type getType()
+ {
+ return Type.TEST;
+ }
+ };
+ TestPlan plan = TestPlan.from( Collections.singletonList( engine ) );
+
+ adapter.testPlanExecutionStarted( plan );
+ adapter.executionStarted( TestIdentifier.from( engine ) );
+ InOrder inOrder = inOrder( listener );
+ inOrder
+ .verify( listener )
+ .testSetStarting( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "engine" ) );
+ inOrder.verify( listener ).testStarting( new SimpleReportEntry( "<unrooted>", "engine" ) );
+ inOrder.verifyNoMoreInteractions();
+
+ adapter.executionFinished( TestIdentifier.from( engine ), successful() );
+ inOrder = inOrder( listener );
+ inOrder.verify( listener ).testSucceeded( new SimpleReportEntry( "<unrooted>", "engine" ) );
+ inOrder
+ .verify( listener )
+ .testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "engine" ) );
+ inOrder.verifyNoMoreInteractions();
}
@Test
void notNotifiedWhenEngineExecutionStarted()
+ throws Exception
{
adapter.executionStarted( newEngineIdentifier() );
verify( listener, never() ).testStarting( any() );
@@ -93,7 +260,7 @@ class RunListenerAdapterTests
@Test
void notifiedWhenMethodExecutionSkipped()
- throws Exception
+ throws Exception
{
adapter.executionSkipped( newMethodIdentifier(), "test" );
verify( listener ).testSkipped( any() );
@@ -101,19 +268,27 @@ class RunListenerAdapterTests
@Test
void notifiedWithCorrectNamesWhenClassExecutionSkipped()
+ throws Exception
{
ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+ TestPlan testPlan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
+ adapter.testPlanExecutionStarted( testPlan );
- adapter.executionSkipped( newClassIdentifier(), "test" );
+ TestIdentifier classIdentifier =
+ identifiersAsParentOnTestPlan( testPlan, newEngineDescriptor(), newClassDescriptor() );
+
+ adapter.executionSkipped( classIdentifier, "test" );
verify( listener ).testSkipped( entryCaptor.capture() );
ReportEntry entry = entryCaptor.getValue();
assertTrue( MyTestClass.class.getTypeName().contains( entry.getName() ) );
- assertEquals( MyTestClass.class.getName(), entry.getSourceName() );
+ assertEquals( MyTestClass.class.getTypeName(), entry.getSourceName() );
}
@Test
void notifiedWhenEngineExecutionSkipped()
+ throws Exception
{
adapter.executionSkipped( newEngineIdentifier(), "test" );
verify( listener ).testSkipped( any() );
@@ -121,7 +296,7 @@ class RunListenerAdapterTests
@Test
void notifiedWhenMethodExecutionAborted()
- throws Exception
+ throws Exception
{
adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.aborted( null ) );
verify( listener ).testAssumptionFailure( any() );
@@ -129,57 +304,89 @@ class RunListenerAdapterTests
@Test
void notifiedWhenClassExecutionAborted()
+ throws Exception
{
adapter.executionFinished( newClassIdentifier(), TestExecutionResult.aborted( null ) );
verify( listener ).testAssumptionFailure( any() );
}
@Test
- void notifiedWhenMethodExecutionFailed()
- throws Exception
+ void notifiedWhenMethodExecutionFailedWithAnAssertionError()
+ throws Exception
{
- adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.failed( new RuntimeException() ) );
+ adapter.executionFinished(
+ newMethodIdentifier(), TestExecutionResult.failed( new AssertionError() ) );
verify( listener ).testFailed( any() );
}
@Test
+ void notifiedWhenMethodExecutionFailedWithANonAssertionError()
+ throws Exception
+ {
+ adapter.executionFinished(
+ newMethodIdentifier(), TestExecutionResult.failed( new RuntimeException() ) );
+ verify( listener ).testError( any() );
+ }
+
+ @Test
void notifiedWithCorrectNamesWhenClassExecutionFailed()
+ throws Exception
{
ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+ TestPlan testPlan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
+ adapter.testPlanExecutionStarted( testPlan );
- adapter.executionFinished( newClassIdentifier(), TestExecutionResult.failed( new RuntimeException() ) );
+ adapter.executionFinished(
+ identifiersAsParentOnTestPlan( testPlan, newEngineDescriptor(), newClassDescriptor() ),
+ TestExecutionResult.failed( new AssertionError() ) );
verify( listener ).testFailed( entryCaptor.capture() );
ReportEntry entry = entryCaptor.getValue();
- assertEquals( MyTestClass.class.getName(), entry.getSourceName() );
+ assertEquals( MyTestClass.class.getTypeName(), entry.getSourceName() );
assertNotNull( entry.getStackTraceWriter() );
}
@Test
void notifiedWhenMethodExecutionSucceeded()
- throws Exception
+ throws Exception
{
- adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.successful() );
+ adapter.executionFinished( newMethodIdentifier(), successful() );
verify( listener ).testSucceeded( any() );
}
@Test
- void notNotifiedWhenClassExecutionSucceeded()
+ void notifiedForTestSetWhenClassExecutionSucceeded()
+ throws Exception
{
- adapter.executionFinished( newClassIdentifier(), TestExecutionResult.successful() );
+ EngineDescriptor engineDescriptor = newEngineDescriptor();
+ TestDescriptor classDescriptor = newClassDescriptor();
+ engineDescriptor.addChild( classDescriptor );
+ adapter.testPlanExecutionStarted( TestPlan.from( singleton( engineDescriptor ) ) );
+ adapter.executionStarted( TestIdentifier.from( classDescriptor ) );
+
+ adapter.executionFinished( TestIdentifier.from( classDescriptor ), successful() );
+
+ verify( listener )
+ .testSetCompleted(
+ new SimpleReportEntry(
+ JUnitPlatformProvider.class.getName(),
+ MyTestClass.class.getName() ) );
verify( listener, never() ).testSucceeded( any() );
}
@Test
void notifiedWithParentDisplayNameWhenTestClassUnknown()
+ throws Exception
{
// Set up a test plan
- TestPlan plan = TestPlan.from( singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
+ TestPlan plan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) );
adapter.testPlanExecutionStarted( plan );
// Use the test plan to set up child with parent.
final String parentDisplay = "I am your father";
- TestIdentifier child = newSourcelessIdentifierWithParent( plan, parentDisplay );
+ TestIdentifier child = newSourcelessChildIdentifierWithParent( plan, parentDisplay, null );
adapter.executionStarted( child );
// Check that the adapter has informed Surefire that the test has been invoked,
@@ -189,36 +396,117 @@ class RunListenerAdapterTests
assertEquals( parentDisplay, entryCaptor.getValue().getSourceName() );
}
+ @Test
+ void stackTraceWriterPresentWhenParentHasSource()
+ throws Exception
+ {
+ TestPlan plan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Some Plan" ) ) );
+ adapter.testPlanExecutionStarted( plan );
+
+ TestIdentifier child =
+ newSourcelessChildIdentifierWithParent( plan, "Parent", ClassSource.from( MyTestClass.class ) );
+ adapter.executionFinished( child, TestExecutionResult.failed( new RuntimeException() ) );
+ ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+ verify( listener ).testError( entryCaptor.capture() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter() );
+ }
+
+ @Test
+ void stackTraceWriterDefaultsToTestClass()
+ throws Exception
+ {
+ TestPlan plan =
+ TestPlan.from( Collections.singletonList( new EngineDescriptor( newId(), "Some Plan" ) ) );
+ adapter.testPlanExecutionStarted( plan );
+
+ TestIdentifier child = newSourcelessChildIdentifierWithParent( plan, "Parent", null );
+ adapter.executionFinished( child, TestExecutionResult.failed( new RuntimeException( "message" ) ) );
+ ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+ verify( listener ).testError( entryCaptor.capture() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter().smartTrimmedStackTrace() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter().writeTraceToString() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter().writeTrimmedTraceToString() );
+ }
+
+ @Test
+ void stackTraceWriterPresentEvenWithoutException()
+ throws Exception
+ {
+ adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.failed( null ) );
+ ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+ verify( listener ).testError( entryCaptor.capture() );
+ assertNotNull( entryCaptor.getValue().getStackTraceWriter() );
+ }
+
+ @Test
+ void displayNamesIgnoredInReport()
+ throws NoSuchMethodException
+ {
+ TestMethodTestDescriptor descriptor =
+ new TestMethodTestDescriptor(
+ newId(), MyTestClass.class,
+ MyTestClass.class.getDeclaredMethod( "myNamedTestMethod" ) );
+
+ TestIdentifier factoryIdentifier = TestIdentifier.from( descriptor );
+ ArgumentCaptor<ReportEntry> entryCaptor = ArgumentCaptor.forClass( ReportEntry.class );
+
+ adapter.executionSkipped( factoryIdentifier, "" );
+ verify( listener ).testSkipped( entryCaptor.capture() );
+
+ ReportEntry value = entryCaptor.getValue();
+
+ assertEquals( "myNamedTestMethod", value.getName() );
+ }
+
private static TestIdentifier newMethodIdentifier()
- throws Exception
+ throws Exception
{
- TestDescriptor testDescriptor = new TestMethodTestDescriptor( newId(), MyTestClass.class,
- MyTestClass.class.getDeclaredMethod( MY_TEST_METHOD_NAME ) );
- return TestIdentifier.from( testDescriptor );
+ return TestIdentifier.from( newMethodDescriptor() );
+ }
+
+ private static TestDescriptor newMethodDescriptor( Class<?>... parameterTypes )
+ throws Exception
+ {
+ return new TestMethodTestDescriptor(
+ UniqueId.forEngine( "method" ),
+ MyTestClass.class,
+ MyTestClass.class.getDeclaredMethod( MY_TEST_METHOD_NAME, parameterTypes ) );
}
private static TestIdentifier newClassIdentifier()
{
- TestDescriptor testDescriptor = new ClassTestDescriptor( newId(), MyTestClass.class );
- return TestIdentifier.from( testDescriptor );
+ return TestIdentifier.from( newClassDescriptor() );
}
- private static TestIdentifier newSourcelessIdentifierWithParent( TestPlan testPlan, String parentDisplay )
+ private static TestDescriptor newClassDescriptor()
+ {
+ return new ClassTestDescriptor(
+ UniqueId.root( "class", MyTestClass.class.getName() ), MyTestClass.class );
+ }
+
+ private static TestIdentifier newSourcelessChildIdentifierWithParent(
+ TestPlan testPlan, String parentDisplay, TestSource parentTestSource )
{
// A parent test identifier with a name.
TestDescriptor parent = mock( TestDescriptor.class );
when( parent.getUniqueId() ).thenReturn( newId() );
when( parent.getDisplayName() ).thenReturn( parentDisplay );
+ when( parent.getLegacyReportingName() ).thenReturn( parentDisplay );
+ when( parent.getSource() ).thenReturn( Optional.ofNullable( parentTestSource ) );
+ when( parent.getType() ).thenReturn( Type.CONTAINER );
TestIdentifier parentId = TestIdentifier.from( parent );
// The (child) test case that is to be executed as part of a test plan.
TestDescriptor child = mock( TestDescriptor.class );
when( child.getUniqueId() ).thenReturn( newId() );
- when( child.isTest() ).thenReturn( true );
+ when( child.getType() ).thenReturn( Type.TEST );
+ when( child.getLegacyReportingName() ).thenReturn( "child" );
// Ensure the child source is null yet that there is a parent -- the special case to be tested.
when( child.getSource() ).thenReturn( Optional.empty() );
- when( child.getParent() ).thenReturn( Optional.of(parent) );
+ when( child.getParent() ).thenReturn( Optional.of( parent ) );
TestIdentifier childId = TestIdentifier.from( child );
testPlan.add( childId );
@@ -229,10 +517,41 @@ class RunListenerAdapterTests
private static TestIdentifier newEngineIdentifier()
{
- TestDescriptor testDescriptor = new EngineDescriptor( newId(), "engine" );
+ TestDescriptor testDescriptor = newEngineDescriptor();
return TestIdentifier.from( testDescriptor );
}
+ private static EngineDescriptor newEngineDescriptor()
+ {
+ return new EngineDescriptor( UniqueId.forEngine( "engine" ), "engine" );
+ }
+
+ private TestDescriptor newTestDescriptor( UniqueId uniqueId, String displayName, Type type )
+ {
+ return new AbstractTestDescriptor( uniqueId, displayName )
+ {
+ @Override
+ public Type getType()
+ {
+ return type;
+ }
+ };
+ }
+
+ private static TestIdentifier identifiersAsParentOnTestPlan(
+ TestPlan plan, TestDescriptor parent, TestDescriptor child )
+ {
+ child.setParent( parent );
+
+ TestIdentifier parentIdentifier = TestIdentifier.from( parent );
+ TestIdentifier childIdentifier = TestIdentifier.from( child );
+
+ plan.add( parentIdentifier );
+ plan.add( childIdentifier );
+
+ return childIdentifier;
+ }
+
private static UniqueId newId()
{
return UniqueId.forEngine( "engine" );
@@ -240,13 +559,22 @@ class RunListenerAdapterTests
private static final String MY_TEST_METHOD_NAME = "myTestMethod";
- private static class MyTestClass {
-
+ private static class MyTestClass
+ {
@Test
void myTestMethod()
{
}
- }
+ @Test
+ void myTestMethod( String foo )
+ {
+ }
+ @DisplayName( "name" )
+ @Test
+ void myNamedTestMethod()
+ {
+ }
+ }
}
diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTests.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTests.java
new file mode 100644
index 0000000..29ca326
--- /dev/null
+++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTests.java
@@ -0,0 +1,105 @@
+package org.apache.maven.surefire.junitplatform;
+
+/*
+ * 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 static org.apache.maven.surefire.testset.TestListResolver.toClassFileName;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Method;
+
+import org.apache.maven.surefire.testset.TestListResolver;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.engine.descriptor.ClassTestDescriptor;
+import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor;
+import org.junit.platform.engine.FilterResult;
+import org.junit.platform.engine.UniqueId;
+
+/**
+ * Unit tests for {@link TestMethodFilter}.
+ *
+ * @since 1.0.3
+ */
+class TestMethodFilterTests
+{
+
+ private final TestListResolver resolver = mock( TestListResolver.class );
+
+ private final TestMethodFilter filter = new TestMethodFilter( this.resolver );
+
+ @Test
+ void includesBasedOnTestListResolver()
+ throws Exception
+ {
+ when( resolver.shouldRun( toClassFileName( TestClass.class ), "testMethod" ) ).thenReturn( true );
+
+ FilterResult result = filter.apply( newTestMethodDescriptor() );
+
+ assertTrue( result.included() );
+ assertFalse( result.excluded() );
+ }
+
+ @Test
+ void excludesBasedOnTestListResolver()
+ throws Exception
+ {
+ when( resolver.shouldRun( toClassFileName( TestClass.class ), "testMethod" ) ).thenReturn( false );
+
+ FilterResult result = filter.apply( newTestMethodDescriptor() );
+
+ assertFalse( result.included() );
+ assertTrue( result.excluded() );
+ }
+
+ @Test
+ void includesTestDescriptorWithClassSource()
+ throws Exception
+ {
+ FilterResult result = filter.apply( newClassTestDescriptor() );
+
+ assertTrue( result.included() );
+ assertFalse( result.excluded() );
+ }
+
+ private static TestMethodTestDescriptor newTestMethodDescriptor()
+ throws Exception
+ {
+ UniqueId uniqueId = UniqueId.forEngine( "method" );
+ Class<TestClass> testClass = TestClass.class;
+ Method testMethod = testClass.getMethod( "testMethod" );
+ return new TestMethodTestDescriptor( uniqueId, testClass, testMethod );
+ }
+
+ private static ClassTestDescriptor newClassTestDescriptor()
+ throws Exception
+ {
+ UniqueId uniqueId = UniqueId.forEngine( "class" );
+ return new ClassTestDescriptor( uniqueId, TestClass.class );
+ }
+
+ public static class TestClass
+ {
+ public void testMethod()
+ {
+ }
+ }
+}
diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilterTests.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilterTests.java
index 98f5b2b..8ecedc7 100644
--- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilterTests.java
+++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilterTests.java
@@ -20,6 +20,7 @@ package org.apache.maven.surefire.junitplatform;
*/
import static java.util.Collections.emptyList;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
@@ -37,20 +38,20 @@ import org.junit.platform.launcher.core.LauncherFactory;
*
* @since 1.0
*/
-public class TestPlanScannerFilterTests
+class TestPlanScannerFilterTests
{
@Test
- void emptyClassAccepted()
+ void emptyClassIsNotAccepted()
{
- assertTrue( newFilter().accept( EmptyClass.class ), "accepts empty class because it is a container" );
+ assertFalse( newFilter().accept( EmptyClass.class ), "does not accept empty class" );
}
@Test
- void classWithNoTestMethodsIsAccepted()
+ void classWithNoTestMethodsIsNotAccepted()
{
- assertTrue( newFilter().accept( ClassWithMethods.class ),
- "accepts class with no @Test methods because it is a container" );
+ assertFalse(
+ newFilter().accept( ClassWithMethods.class ), "does not accept class with no @Test methods" );
}
@Test
@@ -88,12 +89,11 @@ public class TestPlanScannerFilterTests
return new TestPlanScannerFilter( LauncherFactory.create(), new Filter<?>[0] );
}
- private static class EmptyClass
+ static class EmptyClass
{
}
- @SuppressWarnings("unused")
- private static class ClassWithMethods
+ static class ClassWithMethods
{
void method1()
@@ -105,7 +105,7 @@ public class TestPlanScannerFilterTests
}
}
- private static class ClassWithTestMethods
+ static class ClassWithTestMethods
{
@Test
@@ -119,10 +119,9 @@ public class TestPlanScannerFilterTests
}
}
- private static class ClassWithNestedTestClass
+ static class ClassWithNestedTestClass
{
- @SuppressWarnings("unused")
void method()
{
}
@@ -138,7 +137,7 @@ public class TestPlanScannerFilterTests
}
}
- private static class ClassWithDeeplyNestedTestClass
+ static class ClassWithDeeplyNestedTestClass
{
@Nested
@@ -162,7 +161,7 @@ public class TestPlanScannerFilterTests
}
}
- private static class ClassWithTestFactory
+ static class ClassWithTestFactory
{
@TestFactory
@@ -172,7 +171,7 @@ public class TestPlanScannerFilterTests
}
}
- private static class ClassWithNestedTestFactory
+ static class ClassWithNestedTestFactory
{
@Nested
@@ -186,5 +185,4 @@ public class TestPlanScannerFilterTests
}
}
}
-
}
--
To stop receiving notification emails like this one, please contact
sor@apache.org.