Integration testing in maven - With Maven, Cargo, httpunit and Selenium
by
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/integration/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>integrationtest</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>**/integration/**/*Test*.java</include>
<include>**/integration/**/*Test.java</include>
<include>**/integration/**/*TestCase.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
I tried to run the tests, but unfortunately when it gets to the second round of tests - which should run my integration tests - it runs the same sets of as it ran the first time. I tried adding the combine.children="append"
attribute to the includes, and excludes but that didn't work either. Finally I came across a source file XppDom, part of plexus which maven uses. XppDom allowed the combine.children attribute as well as another I haven't seen mentioned anywhere else childMergeOverride
. I added that instead and it worked!
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/integration/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>integrationtest</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes childMergeOverride="true">
<exclude>none</exclude>
</excludes>
<includes childMergeOverride="true">
<include>**/integration/**/*Test*.java</include>
<include>**/integration/**/*Test.java</include>
<include>**/integration/**/*TestCase.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
Setting it up for Cargo
I've done this on a few projects, the first was a project that built a series of taglibs which are used across a number of applications. The release for the project is a jar so I have a separate test web-app structure in${baseDir}/src/test/web-app
. The code for generating this war looks like this:
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<executions>
<execution>
<id>generate-test-war</id>
<phase>pre-integration-test</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
<configuration>
<warSourceDirectory>${basedir}/src/test/webapp</warSourceDirectory>
<warName>${project.artifactId}-test</warName>
<webappDirectory>${basedir}/target/${project.artifactId}-test</webappDirectory>
<primaryArtifact>false</primaryArtifact>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
During the pre-integration-test phase the above simple generates a test war. If you're project is a web-app and it already generates a war you can skip the above as one will be generated for you already.
The next step for was then to get Cargo to deploy the application:
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>false</wait>
<container>
<containerId>tomcat5x</containerId>
<zipUrlInstaller>
<url>${integrationtests.tomcatURL}</url>
<installDir>${installDir}</installDir>
</zipUrlInstaller>
<output>
${project.build.directory}/tomcat5x.log
</output>
<log>${project.build.directory}/cargo.log</log>
</container>
<configuration>
<home>
${project.build.directory}/tomcat5x/container
</home>
<properties>
<cargo.logging>high</cargo.logging>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</configuration>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
<goal>deploy</goal>
</goals>
<configuration>
<wait>false</wait>
<deployer>
<deployables>
<deployable>
<location>${basedir}/target/${project.artifactId}-test.war</location>
<type>war</type>
<pingURL>http://localhost:8080/${project.artifactId}-test/index.html</pingURL>
<pingTimeout>300000</pingTimeout>
<properties>
<context>${project.artifactId}-test</context>
</properties>
</deployable>
</deployables>
</deployer>
</configuration>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
Most of this is pretty self explanatory, I try to use parameters to configure as much as I can and try to maintain it in higher level POMs wherever appropriate. This is especially true for the tomcat URL which changes on a regular basis. The seem to post new releases and remove the older ones, and it can be a chore to keep up in multiple projects. You may want to look at the cargo plugin documentation, you can ignore some of what I'm doing above if you're project's default artifact (the one package creates) is a web-app.
So there you have it, eventually I got there after a lot of digging. I've been pretty brief in my explanations and have assumed a fairly good understanding of maven. if you have any questions by all means leave a comment and I'll do my best to make it clearer.Related articles by Zemanta
- Testing Is Not Technically Hard, It Is Hard Because It Requires Clear Thought and Understanding
- Why do we (not) write tests
[[posterous-content:xEkrcgitujefewHaqcIv]]
Subscribe via RSS