Integration Tests Part 4 - Nexus Plugins Integration Test

October 26, 2009 By Marvin Froeder

4 minute read time

Continuing the series of articles, let's check how we do integration tests for nexus plugins.

The kungfu virus scanner

The kungfu virus scanner is a simple nexus plugin. It will prevent nexus from caching infected files (it will still serve the file, but won't cache it). To know if a file is infected or not, there is a "sophisticated" algorithm that checks if the file has the word "infected" in its name. It is used for demonstration purposes only and is useless for everything else. You can download its source files here.

To run our test, first of all, we will need a Nexus instance that will be launched and used to hold the plugin being tested. Originally we used the maven-dependency-plugin to unpack the Nexus bundle. Then, we used the same to copy the plugin under test to nexus plugin-repository directory. This alone would mean about 20 lines in the POM and no potential for reuse between different plugins, so we decided to write a specific testing plugin to create the environment required by Nexus plugins. Thus was born the nexus-test-environment-maven-plugin (we should come up with a shorter name =D ).

The nexus-test-environment-maven-plugin copies the Nexus instance, the nexus-plugin, the plugins on which the plugin under test depends, and any extra asserts that need to be copied to Nexus or its environment. The plugin allocates random ports used to load Nexus or other services. It also creates a properties file with all the paths and ports. And a few more things... Here is an example of a basic use:

<plugin>
        <groupId>org.sonatype.plugins</groupId>
        <artifactId>nexus-test-environment-maven-plugin</artifactId>
        <version>1.2</version>
        <executions>
          <execution>
            <goals>
              <goal>setup-nexus-plugin-environment</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <nexusVersion>${nexus.version}</nexusVersion>
        </configuration>
      </plugin>

The only required parameter is the Nexus version that should be used to run the plugin. That execution will unpack a Nexus instance, will install the current project as a Nexus plugin, will unpack Maven (useful for some tests), will reserve ports for some services like e-mail, jar server, http proxy and others. You will be able to select to start all these services during the test.

Since our project has unit and integration tests, we will use failsafe-maven-plugin to execute the integration tests:

<plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>failsafe-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Last, but not least, a dependency to nexus test classes. These classes are helpful because they have lots of utility methods to start/stop Nexus, communicate using REST API, automatically deploy files and more.

    <dependency>
      <groupId>org.sonatype.nexus</groupId>
      <artifactId>nexus-test-harness-launcher</artifactId>
      <scope>test</scope>
      <version>${nexus.version}</version>
    </dependency>

Now let's see the test class itself.

public class VirusScannerIT
    extends AbstractNexusProxyIntegrationTest

All integration tests must extend AbstractNexusIntegrationTest. VirusScanner extends AbstractNexusProxyIntegrationTest that is a AbstractNexusIntegrationTest child, which starts a jetty server, which in turn will be used as our remote artifact server. This server will host all files available at '${basedir}/resources/proxyRepo/release-proxy-repo-1'.

This class has 2 test methods. One that will be able to cache the artifact from remote repository and the other that will not cache.

    @Test
    public void download()
        throws Exception
    {
        File file =
            downloadArtifactFromRepository( "release-proxy-repo-1", GavUtil.newGav( "kungfu", "artifact", "1.0" ),
                                            "target/download" );

        Assert.assertTrue( file.exists() );
        Assert.assertTrue( new File( nexusWorkDir, "storage/release-proxy-repo-1/kungfu/artifact/1.0/artifact-1.0.jar" ).exists() );
    }

This test downloads the artifact, check if the file was downloaded and then check if it was cached.

    @Test
    public void downloadInfected()
        throws Exception
    {
        File file =
            downloadArtifactFromRepository( "release-proxy-repo-1", GavUtil.newGav( "kungfu", "infected-artifact",
                                                                                    "1.0" ), "target/download" );

        Assert.assertTrue( file.exists() );
        Assert.assertFalse( new File( nexusWorkDir,
                                      "storage/release-proxy-repo-1/kungfu/infected-artifact/1.0/infected-artifact-1.0.jar" ).exists() );
    }

It does basically the same thing. But this time it asserts that the infected artifact was not cached.

Nexus will be started once per integration class. This means download() and downloadInfected() will run in same Nexus instance without being restarted.

Last, but not least, we have the test coverage. It uses Emma to instrument, merge and write the report. Check the POM or previous articles in this series to get acquainted with Emma and integration tests.

Now that integration tests take much more time and machine resources to run, it is preferred to use a unit test instead whenever possible. For instance we could check a complex rule for the virus scanner using an UT like this one.

In the next article of this series we will see how to get coverage reports for UI test using Selenium.

Tags: Sonatype Says

Written by Marvin Froeder

Over the past 11 years, Marvin has worked for several startups, most notably at The Last Pickle, ContaAzul, and Sonatype, where he was a Java Developer.