Skip to content

Commit

Permalink
[SUREFIRE-1330] JUnit 5 surefire-provider code donation
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibor17 authored and sormuras committed Jun 7, 2018
1 parent cb4f152 commit a132614
Show file tree
Hide file tree
Showing 43 changed files with 3,916 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,15 @@ public abstract class AbstractSurefireMojo
@Parameter( property = "junitArtifactName", defaultValue = "junit:junit" )
private String junitArtifactName;

/**
* Allows you to specify the name of the JUnit Platform artifact.
* If not set, {@code org.junit.platform:junit-platform-engine} will be used.
*
* @since 2.22.0
*/
@Parameter( property = "junitPlatformArtifactName", defaultValue = "org.junit.platform:junit-platform-engine" )
private String junitPlatformArtifactName;

/**
* Allows you to specify the name of the TestNG artifact. If not set, {@code org.testng:testng} will be used.
*
Expand Down Expand Up @@ -1057,6 +1066,7 @@ protected List<ProviderInfo> createProviders()
Artifact junitDepArtifact = getJunitDepArtifact();
return new ProviderList( new DynamicProviderInfo( null ),
new TestNgProviderInfo( getTestNgArtifact() ),
new JUnitPlatformProviderInfo( getJunitPlatformArtifact() ),
new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
new JUnit3ProviderInfo() )
Expand Down Expand Up @@ -1575,7 +1585,7 @@ private boolean isAnyJunit4( Artifact artifact )
return dependencyResolver.isWithinVersionSpec( artifact, "[4.0,)" );
}

static boolean isForkModeNever( String forkMode )
private static boolean isForkModeNever( String forkMode )
{
return FORK_NEVER.equals( forkMode );
}
Expand Down Expand Up @@ -2068,6 +2078,21 @@ private Artifact getJunitDepArtifact()
return getProjectArtifactMap().get( "junit:junit-dep" );
}


private Artifact getJunitPlatformArtifact()
{
Artifact artifact = getProjectArtifactMap().get( getJunitPlatformArtifactName() );
Artifact projectArtifact = project.getArtifact();
String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();

if ( artifact == null && projectArtifactName.equals( getJunitPlatformArtifactName() ) )
{
artifact = projectArtifact;
}

return artifact;
}

private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration,
@Nonnull ClassLoaderConfiguration classLoaderConfiguration,
@Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
Expand Down Expand Up @@ -2695,7 +2720,8 @@ private void warnIfDefunctGroupsCombinations()
{
Artifact junitArtifact = getJunitArtifact();
boolean junit47Compatible = isJunit47Compatible( junitArtifact );
if ( !junit47Compatible )
boolean junit5PlatformCompatible = getJunitPlatformArtifact() != null;
if ( !junit47Compatible && !junit5PlatformCompatible )
{
if ( junitArtifact != null )
{
Expand All @@ -2704,8 +2730,8 @@ private void warnIfDefunctGroupsCombinations()
+ "Check your dependency:tree to see if your project "
+ "is picking up an old junit version" );
}
throw new MojoFailureException( "groups/excludedGroups require TestNG or JUnit48+ on project test "
+ "classpath" );
throw new MojoFailureException( "groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 "
+ "on project test classpath" );
}
}

Expand Down Expand Up @@ -2908,6 +2934,40 @@ public Classpath getProviderClasspath()

}

final class JUnitPlatformProviderInfo
implements ProviderInfo
{
private final Artifact junitArtifact;

JUnitPlatformProviderInfo( Artifact junitArtifact )
{
this.junitArtifact = junitArtifact;
}

@Nonnull public String getProviderName()
{
return "org.apache.maven.surefire.junitplatform.JUnitPlatformProvider";
}

public boolean isApplicable()
{
return junitArtifact != null;
}

public void addProviderProperties() throws MojoExecutionException
{
convertGroupParameters();
}

public Classpath getProviderClasspath()
throws ArtifactResolutionException, ArtifactNotFoundException
{
return dependencyResolver.getProviderClasspath( "surefire-junit-platform",
surefireBooterArtifact.getBaseVersion(),
null );
}
}

final class JUnitCoreProviderInfo
implements ProviderInfo
{
Expand Down Expand Up @@ -3364,6 +3424,17 @@ public void setJunitArtifactName( String junitArtifactName )
this.junitArtifactName = junitArtifactName;
}

public String getJunitPlatformArtifactName()
{
return junitPlatformArtifactName;
}

@SuppressWarnings( "UnusedDeclaration" )
public void setJunitPlatformArtifactName( String junitPlatformArtifactName )
{
this.junitPlatformArtifactName = junitPlatformArtifactName;
}

public String getTestNGArtifactName()
{
return testNGArtifactName;
Expand Down
200 changes: 200 additions & 0 deletions maven-surefire-plugin/src/site/apt/examples/junit-platform.apt.vm
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
------
Using JUnit 5 Platform
------
JUnit Lambda Team <junit-lambda-team@googlegroups.com>
------
2018-05-14
------

~~ 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.

~~ NOTE: For help with the syntax of this file, see:
~~ http://maven.apache.org/doxia/references/apt-format.html

Using JUnit 5 Platform

* Configuring JUnit Platform

To get started with JUnit Platform, you need to add at least a single <<<TestEngine>>> implementation
to your project. For example, if you want to write tests with Jupiter, add the test artifact
<<<junit-jupiter-engine>>> to the dependencies in POM:

+---+
<dependencies>
[...]
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
[...]
</dependencies>
+---+

This will pull in all required dependencies. Among those dependencies is <<<junit-jupiter-api>>> which contains
the classes and interfaces your test source requires to compile. <<<junit-platform-engine>>> is also resolved and
added.

This is the only step that is required to get started - you can now create tests in your test source directory
(e.g., <<<src/test/java>>>).

If you want to write and execute JUnit 3 or 4 tests via the JUnit Platform add the Vintage Engine to the
dependencies:

+---+
<dependencies>
[...]
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
[...]
</dependencies>
+---+

* Provider Selection

If nothing is configured, Surefire detects which JUnit version to use by the following algorithm:

+---+
if the JUnit 5 Platform Engine is present in the project
use junit-platform
if the JUnit version in the project >= 4.7 and the <<<parallel>>> configuration parameter has ANY value
use junit47 provider
if JUnit >= 4.0 is present
use junit4 provider
else
use junit3.8.1
+---+

When using this technique there is no check that the proper test-frameworks are present on your project's
classpath. Failing to add the proper test-frameworks will result in a build failure.

* Running Tests in Parallel

From JUnit Platform does not support running tests in parallel.

* Running a Single Test Class

The JUnit Platform Provider supports the <<<test>>> JVM system property supported by
the Maven Surefire Plugin. For example, to run only test methods in the <<<org.example.MyTest>>> test class
you can execute <<<mvn -Dtest=org.example.MyTest test>>> from the command line.


* Filtering by Test Class Names

The Maven Surefire Plugin will scan for test classes whose fully qualified names match
the following patterns.

* <<<**/Test*.java>>>

* <<<**/*Test.java>>>

* <<<**/*Tests.java>>>

* <<<**/*TestCase.java>>>

Moreover, it will exclude all nested classes (including static member classes) by default.

Note, however, that you can override this default behavior by configuring explicit
`include` and `exclude` rules in your `pom.xml` file. For example, to keep Maven Surefire
from excluding static member classes, you can override its exclude rules.

* Overriding exclude rules of Maven Surefire

+---+
...
<build>
<plugins>
...
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<configuration>
<excludes>
<exclude>some test to exclude here</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
...
+---+


* Filtering by Tags

You can use JUnit5 Tags and filter tests by tags or tag expressions.

* to include <<<tags>>> or <<<tag expressions>>>, use <<<groups>>>.

* to exclude <<<tags>>> or <<<tag expressions>>>, use either <<<excludedGroups>>>.

+---+
...
<build>
<plugins>
...
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<configuration>
<groups>acceptance | !feature-a</groups>
<excludedGroups>integration, regression</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
...
+---+


* Configuration Parameters

You can set JUnit Platform configuration parameters to influence test discovery and execution by
declaring the <<<configurationParameters>>> property and providing key-value pairs using the Java
<<<Properties>>> file syntax (as shown below) or via the <<<junit-platform.properties>>> file.

+---+
...
<build>
<plugins>
...
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<configuration>
<properties>
<configurationParameters>
junit.jupiter.conditions.deactivate = *
junit.jupiter.extensions.autodetection.enabled = true
junit.jupiter.testinstance.lifecycle.default = per_class
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
</build>
...
+---+
15 changes: 9 additions & 6 deletions maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ Using JUnit
If nothing is configured, Surefire detects which JUnit version to use by the following algorithm:

+---+
if the JUnit version in the project >= 4.7 and the parallel attribute has ANY value
if the JUnit 5 Platform Engine is present in the project
use junit-platform
if the JUnit version in the project >= 4.7 and the <<<parallel>>> configuration parameter has ANY value
use junit47 provider
if JUnit >= 4.0 is present
use junit4 provider
Expand Down Expand Up @@ -256,11 +258,12 @@ else
<plugins>
[...]
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<groups>com.mycompany.SlowTests</groups>
</configuration>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<configuration>
<groups>com.mycompany.SlowTests</groups>
</configuration>
</plugin>
[...]
</plugins>
Expand Down
5 changes: 3 additions & 2 deletions maven-surefire-plugin/src/site/apt/examples/providers.apt.vm
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Selecting Providers
override such a selection. This can be done by adding the required provider as a dependency to
the surefire-plugin.

The following example shows how to force usage of the Junit 4.7 provider:
The following example shows how to force usage of the JUnit 4.7 provider:

+---+
<plugins>
Expand All @@ -56,7 +56,8 @@ Selecting Providers
</plugins>
+---+

The providers supplied with Surefire are <<<surefire-junit3>>>, <<<surefire-junit4>>>, <<<surefire-junit47>>> and <<<surefire-testng>>>.
The providers supplied with Surefire are <<<surefire-junit3>>>, <<<surefire-junit4>>>, <<<surefire-junit47>>>,
<<<surefire-junit-platform>>> and <<<surefire-testng>>>.
Please note that forcing a provider still requires that the test framework is properly set up on your project classpath.

You can also specify multiple providers as dependencies, and they will all be run and produce a common report.
Expand Down
Loading

0 comments on commit a132614

Please sign in to comment.