Sunday, June 10, 2007

Integration Testing in your Maven Application

The problem:

You want to create integration tests in your Maven project. You don't want these tests to run every time you compile.

The solution:

Create some profiles in your pom.xml. You can create a profile that by default excludes running any test that starts or ends with the words 'IntegrationTest'. You can then include a profile that will run these tests when activated.

Here is an example you can use in your pom:
 
<!-- Use this profile to allow integration tests to run -->
<profiles>
<profile>
<id>no_integration_testing</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/IntegrationTest*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>integration_testing</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/IntegrationTest*.java</include>
</includes>
<excludes>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
If you use this configuration, by default a test called "LegacySystemIntegrationTest" would not get run by surefire when you compile. If you issue the command
"mvn -P integration_testing compile"
then this integration test (and any others named in this fashion) will get run. Note there are some gotchas when using this strategy:
  1. If you include the profiles above in a pom that gets inherited, the pom which inherits may override the default excludes. If the sub-pom does override excludes the entries from the profile go away and tests with "IntegrationTest" in them will get run by Surefire.
  2. Any integration tests that do not start or end with "IntegrationTest" will get run. You are expected to follow a convention here. You could add more excludes and incluedes to my example above in this case though.
My advice is that you use this configuration, and by convention always name integration tests with "IntegrationTest" in them. It saves headaches and normalizes development across all users.