I have a multi-module maven project with both integration and unit tests in the same folder (src/test/java). Integration tests are marked with @Category(IntegrationTest.class)
. I want to end up with the following setup:
- If I run
mvn install
, I want all tests to compile, but I do not want to execute any. - If I run
mvn test
, I want all tests to compile, but execute only unit tests. - If I run
mvn integration-test
, I want to compile and execute all tests.
The important point is, I want this configured in the pom.xml
without any extra commandline arguments.
Currently I came up with the following setup in my parent pom.xml, where the only problem is #1, where all tests are executed:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${project.java.version}</source>
<target>${project.java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<configuration>
<includes>
<include>**/*.class</include>
</includes>
<excludedGroups>cz.cuni.xrg.intlib.commons.IntegrationTest</excludedGroups>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<configuration>
<groups>cz.cuni.xrg.intlib.commons.IntegrationTest</groups>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<includes>
<include>**/*.class</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
All child modules have the following plugin configuration in their pom.xml, which I believe should inherit from the parent pom:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
</plugins>
</build>
I tried using <skipTests>true</skipTests>
, but it disables test execution for all goals, which is not what I want (violates #2 and #3). It is also quite weird, that mvn test
honors the skipTests=true
option...why would I want to run it in the first place??
After hours of googling and trying different combinations, I am hesitant whether it is even possible to not run tests in mvn install
, while at the same time run them in mvn test
. I hope someone proves this wrong. ;)
I am also willing to accept a solution, where mvn install
would execute only unit tests, but I don't think it makes much difference.
What OP stated in his question:
is perfectly valid and extremely easy to achieve.
EDIT: except first condition, which acts againts the maven nature. The best way here would be simply do
mvn install -DskipTests
All you need is following snippet in
pom.xml
:and to stick to the maven naming conventions for unit and integration tests (as @khmarbaise already stated). So generally name you integration tests with
IT
suffix (for exampleMyIntegrationTestIT.java
) and letmaven-failsafe
do its job.In that way, you do not even need JUnit categories (although sometimes they can be quite useful).
That's it :)
mvn test
executes only unit testsmvn integration-test
executes all testsmvn failsafe:integration-test
runs only integration testsmvn clean verify
when you want to be sure, that whole project just worksSome personal advices
Keeping integration tests separately from unit tests lets you easily run within your IDE all tests in some package. Usually additional directory called
test-integration
(orintegrationtest
) is used for this purpose.This is also easy to achieve with maven:
And then move your integration tests to that directory. It should look like:
Integration tests usually needs more memory:
It sounds like you didn't understand the concept of the build life-cycle in Maven. If you run
mvn install
all life-cycle phases (including theinstall
phase itself) run before the install phase. This means running the following phases:which means in other words the
test
as well asintegration-test
life-cycle phases are included. So without any supplemental information it's not possible to change the behaviour as you wish it.It could be achieved by using a profile in Maven:
So your first requirement:
mvn install
, I want all tests to compile, but I do not want to execute any.can be achieved by using the following:
mvn test
, I want all tests to compile, but execute only unit tests.This can simply achieved by using the plain call:
cause the integration tests phase is not run (see the build life cycle).
mvn integration-test
, I want to compile and execute all tests.This means running the default which includes running the
test
phase which will run the unit tests (maven-surefire-plugin) and furthermore running the integration test which are handled by the maven-failsafe-plugin. But you should be aware that if you like to call the integration tests you should using the following command:instead, cause you missed the
post-integration-test
phase in your previous call.Apart from the above you should follow the naming conventions for unit and integration tests where unit tests should be named like the following:
and integration tests should be named like the following:
I hope you have configured the maven-failsafe-plugin like the following which is needed to bound the maven-failsafe-plugin to the correct life-cycle-phases:
as you correctly did, but you should be aware that the
include
tags work on the source code (.java) and not on the compiled names (.class). I wouldn't use the Category annotation, just simply using the naming conventions makes the pom simpler and shorter.According to the Failsafe Plugin documentation
is what you want.
mvn test-compile
does exactly what you are looking for. You can simply replacemvn install
withmvn test-compile
and you are done. No need to customise the pom file or anything. The below linked question is similar around #1:Maven - How to compile tests without running them ?
mvn test-compile
should be accepted as the best answer as Maven supports exactly what you want to do natively and without any magic. You would end up with this:This post explains how to skip integration tests, no matter what plugin you are using for these tests.
Basically, what you do is define a profile and put all your integration-tests related xml code inside that profile. Than you activate it when a property
-DskipIntegrationTests
is missing.You can do the same for unit tests: write a profile and activate it when
-DskipUnitTests
is missing.Then, you could do:
The maven-failsafe-plugin docs has a section titled "Skipping by Default."
Sadly, the steps that page describes don't work as written. However, a slight change to those steps will make it work:
In the
properties
section ofpom.xml
, add this:<skipITs>true</skipITs>
Then add the
skipTests
property to theplugin
section of maven-failsafe-plugin:So now, an
mvn install
by default will execute unit tests, but not integration tests.But an
mvn install -DskipITs=false
will execute both unit tests and integration tests.Footnote: Bad documentation played a big part on why Maven was so disliked for such a long time.