There are several ways to achive that. Both of that have pros and cons.
Unpack shared tests
Maven can attach multiple artifacts to each modules (e.g. sources or tests, etc.).
First step is to attach test classes of the shared module.
<build>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<!-- ... -->
</build>
After this it's easy to use in an other project as a dependency:
<dependencies>
<dependency>
<groupId>io.github.zforgo.stackoverflow</groupId>
<artifactId>shared-tests</artifactId>
<version>0.1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
In the dependent project or module shared tests should unpack.
<build>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>share-tests</id>
<phase>generate-test-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>io.github.zforgo.stackoverflow</groupId>
<artifactId>shared-tests</artifactId>
<version>0.1.0-SNAPSHOT</version>
<classifier>tests</classifier>
<outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- ... -->
</build>
NOTE: the ArtifactItem ignores type attribute so the classifier attribute should used instead of type. There is an issue in maven-dependency-plugin issue tracking system. MDEP-732
During unit or integration test phase the unpacked classes will run.
[INFO] ---------------< io.github.zforgo.stackoverflow:project >---------------
[INFO] Building project 0.1.0-SNAPSHOT [3/3]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.1.2:unpack (share-tests) @ project ---
[INFO] Configured Artifact: io.github.zforgo.stackoverflow:shared-tests:tests:0.2.0-SNAPSHOT:jar
[INFO] Unpacking /work/source/stackoverflow/junit-test-sharing/multimodule-test-sharing/shared-tests/target/shared-tests-0.1.0-SNAPSHOT-tests.jar to /work/source/stackoverflow/junit-test-sharing/multimodule-test-sharing/project/target/test-classes with includes "" and excludes ""
[INFO]
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ project ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running io.github.zforgo.stackoverflow.shared.SharedUnitTest
>>>> THIS IS A SHARED UNIT TEST <<<<
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 s - in io.github.zforgo.stackoverflow.shared.SharedUnitTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-failsafe-plugin:3.0.0-M5:integration-test (default) @ project ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running io.github.zforgo.stackoverflow.shared.SharedIntegrationTestIT
>>>> THIS IS A SHARED INTEGRATION TEST <<<<
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s - in io.github.zforgo.stackoverflow.shared.SharedIntegrationTestIT
| Pros |
Cons |
| Both unit and integration tests shared in one step. |
Needs a workaround cause of MDEP-732 |
| Shared tests will be packed into dependent artifact. Prevent changes. |
Class duplication makes dependent test-jar bigger unnecessarily. |
| Inclusion and exclusion supported during unpack. |
|
Using failsafe and surefire plugins' <dependenciesToScan> attribute (recommended)
First of all I'd like to say thanks to @khmarbaise for suggestion.
Fortunately both maven-surefire-plugin and maven-failsafe-plugin has <dependenciesToScan> configuration attribute. All those listed dependencies will be scanned for test classes to include and run.
NOTE Listed artifacts must be <dependency> elements in the dependent project or module.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.zforgo.stackoverflow</groupId>
<artifactId>shared-tests-aggregator</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>project</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>shared-tests</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<dependenciesToScan>
<dependency>${project.groupId}:shared-tests:test-jar</dependency>
</dependenciesToScan>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<dependenciesToScan>
<dependency>${project.groupId}:shared-tests:test-jar</dependency>
</dependenciesToScan>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
NOTE: maven-failsafe-plugin:integration-test goal will report false error messages to console if the same package is missing in the dependent project.
[INFO]
[INFO] --- maven-failsafe-plugin:3.0.0-M5:integration-test (default) @ project ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[ERROR] WARNING: package io.github.zforgo.stackoverflow.shared not in project
[INFO] Running io.github.zforgo.stackoverflow.shared.SharedIntegrationTestIT
>>>> THIS IS A SHARED INTEGRATION TEST <<<<
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.034 s - in io.github.zforgo.stackoverflow.shared.SharedIntegrationTestIT
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
| Pros |
Cons |
| Easy to separate unit- and integration test sharing |
Configuration must be duplicated when unit- and integration tests are shared |
| Shared tests wont copied, no class duplication |
Delusive [ERROR] messages in logs but build is success. |
| Responsible plugins will handle dependent test classes |
Possible configuration changes time to time, version to version. Always read the documentation |
Using build-helper-maven-plugin
This MojoHaus plugin allows to use multiple source or test-source directories in one module or project.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.zforgo.stackoverflow</groupId>
<artifactId>shared-tests</artifactId>
<version>0.1.0-SHAPSHOT</version>
</parent>
<artifactId>project</artifactId>
<dependencies>
<dependency>
<groupId>io.github.zforgo.stackoverflow</groupId>
<artifactId>shared-test</artifactId>
<version>0.1.0-SHAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${project.parent.basedir}/shared-test/src/test/java/com/example/demo/shared</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
| Pros |
Cons |
|
Works only with local folders. External artifacts not supported. |
|
Folders are hardcoded. Maintenance issues. |
In short there are more possibilities to share tests between projects and modules but it's your turn to chose the best one.