On one of my current projects we want to separate the fast unit tests from the slow running integration and acceptance tests. Using Maven this is not possible out of the box because Maven only supports two source folders,
main and
test. How can we add another source and resource folder, e.g.
it (for integration test)? Let's assume a project layout like that:
project
|-- pom.xml
`-- src
|-- main
`-- java
|-- test
`-- java
`-- UnitTest.java
`-- it
`-- java
`-- IntegrationIT.java
We use the regular
Maven Surefire to execute our unit tests, i.e. all the tests in the
src/test/java
folder. The plugin definition in the
pom.xml
is as expected.
<plugin>
<!-- run the regular tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
</plugin>
And we use
Maven Failsafe to execute the integration tests. If you do not know Failsafe, it is much like the Surefire plugin, but with different defaults and usually runs during the integration test phase.
<plugin>
<!-- run the integration tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
By default the Failsafe plugin does not look for class names ending with
Test
but ending with
IT
, making it possible to mix both kind of tests in the same
src/test/java
folder, but we do not want that. The "trick" to have another source folder for integration tests is to use the
Build Helper Maven Plugin and add it as test source.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>add-integration-test-source-as-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Now
src/it/java
is added as test source as well, as seen during Maven execution. After the compile phase Maven logs
[INFO] [build-helper:add-test-source {execution: add-integration-test-source-as-test-sources}]
[INFO] Test Source directory: .\src\it\java added.
There is still only one test source for Maven but at least we have two folders in the file system. All test sources get merged and during the test compile phase we see
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] Compiling 2 source files to .\target\test-classes
showing that all classes in both
src/test/java
and
src/it/java
are compiled at the same time. This is important to know because class names must not clash and tests still need different naming conventions like
*Test
and
*IT
. Now
mvn test
will only execute fast unit tests and can be rerun many times during development.
[INFO] [surefire:test {execution: default-test}]
[INFO] Surefire report directory: .\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running UnitTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec - in UnitTest
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Only if we want, using
mvn verify
, the integration tests are executed.
[INFO] [failsafe:integration-test {execution: default}]
[INFO] Failsafe report directory: .\target\failsafe-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running IntegrationIT
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in IntegrationIT
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] [failsafe:verify {execution: default}]
[INFO] Failsafe report directory: .\target\failsafe-reports
Now we can run the slow tests before we check in the code or after major changes a few times during the day.