Tags

, , , , , , , ,

Some integration tests and almost all acceptance tests require the availability of a deployed application, and it’s always a good idea to run your tests by deploying the application into the target container itself. Almost all the applications I develop end up running on JBoss, and given JBoss 7′s amazing startup times and Cargo supporting JBoss 7 since version 1.1.2, there’s almost no excuse for not running (at least most of) these tests within the main build cycle itself.

The following is a brief outline of how you can configure your Maven build to startup JBoss, run integration tests and shutdown the container once done. Since I don’t like depending on the availability of a JBoss installation as a prerequisite for a build, we will also download the application server as part of the build and process.

More information on the Cargo’s Maven integration can be found in the Cargo Maven 2 Reference Guide, and information on Cargo’s support for JBoss 7 can be found in the Cargo JBoss 7 page.

The End Result

We can download JBoss 7, unpack it, start up the container, deploy the app, run integration tests, and shutdown the container by including the following in our pom.xml and replacing the deployable section with the details of the application artifact. Please check the following sections for a more complete explanation of what’s been done here.

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.cargo</groupId>
      <artifactId>cargo-maven2-plugin</artifactId>
      <!-- JBoss 7 is only supported from this version onwards -->
      <version>1.1.2</version>
      <configuration>
        <container>
          <containerId>jboss7x</containerId>
          <zipUrlInstaller>
            <url>http://download.jboss.org/jbossas/7.0/jboss-as-7.0.0.Final/jboss-as-7.0.0.Final.zip</url>
          </zipUrlInstaller>
        </container>
        <deployer>
          <type>installed</type>
          <deployables>
            <deployable>
              <!-- Artifact to deploy; change to your artifact -->
              <groupId>com.navinpeiris.examples</groupId>
              <artifactId>example-artifact</artifactId>
              <type>war</type>
              <!-- Don't forget to change the following to your apps URL -->
              <pingURL>http://localhost:8080/myapp</pingURL>
              <!-- This is the default; make larger if required -->
              <pingTimeout>20000</pingTimeout>
            </deployable>
          </deployables>
        </deployer>
      </configuration>
      <executions>
        <execution>
          <id>start-container</id>
          <phase>pre-integration-test</phase>
          <goals>
            <goal>start</goal>
            <goal>deploy</goal>
          </goals>
        </execution>
        <execution>
          <id>stop-container</id>
          <phase>post-integration-test</phase>
          <goals>
            <goal>stop</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

The Various Parts

This section aims to provide a more detailed explanation of the what’s been done in the pom file extract above.

Downloading and Unpacking JBoss

Cargo can be configured to download and unpack a container within the target directory by specifying the URL to a ZIP of the container in the zipUrlInstaller element within the container section as follows:

<container>
  <containerId>jboss7x</containerId>
   <zipUrlInstaller>
     <url>http://download.jboss.org/jbossas/7.0/jboss-as-7.0.0.Final/jboss-as-7.0.0.Final.zip</url>
   </zipUrlInstaller>
</container>

Alternatively we can configure Cargo to download the container as a Maven Artifact by using the artifactInstaller element instead of a zipUrlInstaller element. More information on accessing JBoss 7 as a maven artifact can be found here. Please note that in addition to the following, we also need to make sure that we can access the JBoss Maven Repository through the pom, which has been described in the provided link.

<container>
  <containerId>jboss7x</containerId>
  <artifactInstaller>
    <groupId>org.jboss.as</groupId>
    <artifactId>jboss-as-dist</artifactId>
    <version>7.0.0.Final</version>
    <type>zip</type>
  </artifactInstaller>
</container>

Starting and Stopping the Container

We start and stop the container in the pre-integration-test and post-integration-test phases by specifying the executions section of the plugin as shown below:

<executions>
  <execution>
    <id>start-container</id>
    <phase>pre-integration-test</phase>
    <goals>
      <goal>start</goal>
    </goals>
  </execution>
  <execution>
    <id>stop-container</id>
    <phase>post-integration-test</phase>
    <goals>
      <goal>stop</goal>
    </goals>
  </execution>
</executions>

This binds the start and stop phases of the cargo plugin to the relevant integration test phases.

Deploying and Waiting for the Application to Start

We can get Cargo to deploy our application artifact into the container in one of two ways:

  1. Define the artifact as a deployable within the configuration/configuration/deployables section of the plugin. Note that there is a second configuration section in Cargo.
  2. Define the artifact as a deployable within the configuration/deployer/deployables section of the plugin

The first has the advantage that the artifact is deployed before the container is started and therefore has a small startup time speedup. However Cargo doesn’t wait for the artifact to finish deploying before moving to the next lifecycle phase of the build, and therefore we have to resolve to checking the state of the application within our tests.

The second deploys the artifact after the container starts up, and we can specify a URL for Cargo to ping for a specified amount of time using the pingURL and pingTimeout elements. The Cargo documentation says that these elements can be defined in the first method as well, but testing has showed that the plugin doesn’t honour these tags.

Therefore, we specify our application artifact to be deployed using the second method as follows:

<configuration>
  ...
  <deployer>
    <type>installed</type>
    <deployables>
      <deployable>
        <!-- Artifact to deploy; change to your artifact -->
        <groupId>com.navinpeiris.examples</groupId>
        <artifactId>example-artifact</artifactId>
        <type>war</type>
        <!-- Don't forget to change the following to your apps URL -->
        <pingURL>http://localhost:8080/myapp</pingURL>
        <pingTimeout>20000</pingTimeout>
      </deployable>
    </deployables>
  </deployer>
</configuration>

Other Considerations

There are a few other matters that should be considered but are outside the scope of this post:

  1. We should use the maven-failsafe-plugin for integration tests so that the application server is guaranteed to be shutdown even if any integration tests fail.
  2. We should define the above deployment within a maven profile so that we have the ability to use other deployment/container types in the build.
  3. Although we use a downloaded instance of JBoss there is no reason that we can’t use an existing local or remote installation.
  4. If we are using the downloaded instance, then we should configure the ports to non-standard values so that we don’t have port conflicts if/when running multiple simultaneous builds on the same machine.

Summary

This shows how we can use the Cargo plugin to start a JBoss 7 instance and deploy an application artifact before we run our integration tests. We also configured Cargo in such a way that the we wait for the application to complete deployment before starting.

About these ads