Continuing the series of articles, let's check how we do integration tests for Nexus plugins.
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 only for demonstration purposes, and is useless for everything else.
To run our test, we will first 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. Therefore, 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).
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, install the current project as a Nexus plugin, unpack Maven (useful for some tests), reserve ports for some services like e-mail, jar server, http proxy and others. You can 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 can cache the artifact from the 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, checks if the file was downloaded, and then checks 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 the 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, 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.
In the next article of this series, we will see how to get coverage reports for UI tests using Selenium.