Site icon Antonio's Blog

Let’s Turn Integration Tests with Maven to a First-Class Citizen

I would like to thank Arnaud Heritier who gave me plenty of tips and advices to write this blog. In fact if you want to endorse someone on Maven in LinkedIn, he is the man, not me ;o)

If you use Maven in your projects you might wonder what “Let’s Turn Integration Tests with Maven into a First-Class Citizen” means. A bit of introduction on that. Maven is based around the central concept of a build lifecycle and if you look at the default lifecycle bindings  you see the following phases :

As you can see, unit tests are central in Maven. Package your project with mvn package or deploy it with mvn deploy and this will kick the test phase. Why ? Because in the default lifecycle bindings of Maven, the test phase is automatically called through the Surefire plugin. The maven-surefire-plugin is designed for running unit tests and if any of the tests fail then it will fail the build immediately.

So where are the integration tests ? Not in the default lifecycle, that’s for sure. They are handled by a different plugin : Failsafe. The maven-failsafe-plugin is a fork of Surefire designed to run integration tests (after the package phase, on the integration-test phase). But on the contrary of Surefire, Failsafe is not activate by default, you need to explicitelly add it to you pom.xml and attach a phase to it :

[sourcecode language=”xml” highlight=”8,9″]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
[/sourcecode]

The Maven lifecycle has four phases for running integration tests:

The Failsafe Plugin has only 2 goals:

By default, the Surefire plugin executes **/Test*.java, **/*Test.java, and **/*TestCase.java test classes. The Failsafe plugin will look for **/IT*.java, **/*IT.java, and **/*ITCase.java. So if you are using unit test and integration tests, make sure to put them all in src/test/java and use this naming convention.

How does this work ? You run mvn test : unit test are executed. You run mvn verify : unit test and then integration tests are executed. But if unit test fail, integration tests are not passed. Meaning that, for Maven, unit tests are more important than integration test.

How to seperate unit and integration test ?

What I really want is to be able to, either run UT or IT or none of them. Something like :

Here is a little trick you need to do in your pom.xml (again, thanks Arnaud)

[sourcecode language=”xml” highlight=”8,9″]
<project>

<properties>
<skipTests>false</skipTests>
<skipITs>${skipTests}</skipITs>
<skipUTs>${skipTests}</skipUTs>
</properties>

<build>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>${skipTests}</skipTests>
<skipITs>${skipITs}</skipITs>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>${skipUTs}</skipTests>
</configuration>
</plugin>

</plugins>
</build>
</project>
[/sourcecode]

Conclusion

Unit testing is at the heart of Maven… but not integration testing. With this little trick you can put UT and IT at the same level : you can run either both tests, UT only, IT only or none. But it would be good to have this behaviour by default, without any configuration. That would mean adding the integration-test phase to the default lifecycle bindings of Maven.

What do you think ? Shall I start a discussion on the Maven Mailing List ? Create a JIRA issue ? Shall we put integration tests at the same level of unit test ? Any other idea of how we could integrate both more closely ?

Référence

Exit mobile version