Arquillian integration

Lukas Krejci lkrejci at redhat.com
Tue Feb 28 17:27:01 UTC 2012


Hello,

This is just a short notice about and an introduction to the integration between Arquillian testing framework and RHQ's plugin container.

What does this all mean, you say?

We have a long term problem with the not-so-easy testing of our agent plugins. This work is not going to make that a breeze, but will help you get over one of the hurdles.

If you were a plugin developer, you'd know that setting up a plugin container in your tests so that you could do some testing on your code while running in a real "agent-like" environment required quite a bit of setup - you'd have to collect the jars of plugins your plugin is dependent upon, stash them in some directory, create another directory for the "data" the plugin container or plugins can store away, configure the plugin container to use these and then finally start it up. This required both maven and code magic to get in all working. Not impossible but inconvenient to the point where we didn't really bother unless absolutely necessary.

If, God forbid, you had to test the plugin container itself and use a bunch of plugins to test upgrade/deployment/classloading/dependency issues, you know all too well how difficult that was.

Now consider this code:

@PluginContainerInstance(discoverServers = true)
public class MyClass extends Arquillian {
    @Deployment(name = "simplePlugin")
    public static RhqAgentPluginArchive getTestPlugin() {
        return ShrinkWrap.create(RhqAgentPluginArchive.class, "test-plugin-1.0.0.jar")
            .addClasses(TestDiscoveryComponent.class, TestResourceComponent.class)
            .setPluginDescriptor("test-rhq-plugin.xml");
    }

    @DiscoveredResources(plugin = "testPlugin", resourceType = "TestServer")
    private Set<Resource> testResources;
    
    @Test
    public void testPluginDeployed() {
        Assert.assertEquals(testResources.size(), 1, "There should be one resource with the test type");
    }
}

This deploys the plugin that consists of one resource type with TestDiscoverComponent as its discovery class and TestResourceComponent as its component class defined by the test-rhq-plugin.xml plugin descriptor. Prior to each test, there is going to be a server discovery and the discovered resources (for a specified resource type) are going to be stashed in a field. The test code can then easily check the discovery results and see if all data on the resources were correctly set. This is of course skimming over a lot of details - mainly how to set up your environment so that the discovery code of your resource type discovers what you expect, but that part is actually beyond the scope of arquillian integration (even though you *can* use arquillian to startup JBossAS for example).

Now imagine that your plugin depends on other plugins - remember those antrun stanzas we have in virtually every plugin pom?

@PluginContainerInstance(discoverServers = true)
public class MyClass extends Arquillian {
    @Deployment(name = "simplePlugin")
    public static RhqAgentPluginArchive getTestPlugin() {
        return ShrinkWrap.create(RhqAgentPluginArchive.class, "test-plugin-1.0.0.jar")
            .addPackages(true, "org.rhq.plugins.myPlugin")
            .setPluginDescriptor("test-rhq-plugin.xml")
            .withRequiredPluginsFrom(
                DependencyResolvers.use(MavenDependencyResolver.class).includeDependenciesFromPom("pom.xml")
                   .resolveAs(JavaArchive.class, new ScopeFilter("compile", "runtime")));
    }

    @DiscoveredResources(plugin = "testPlugin", resourceType = "TestServer")
    private Set<Resource> testResources;
    
    @Test
    public void testPluginDeployed() {
        Assert.assertEquals(testResources.size(), 1, "There should be one resource with the test type");
    }
}

There are 2 changes from the previous example - the "addPackages()" call to include classes en-mass and the "withRequiredPluginsFrom()" which is being passed the compile and runtime dependencies from the maven's pom.xml of the project. This is going to scan the test-rhq-plugin.xml for the list of plugins it should look for in the provided list of jars (the ones from the pom) and deploy them along with the plugin itself into the plugin container (recursively, of course - if the plugins depend on yet another plugins, they're included, too).

There is one more thing that I figured might be useful in the plugin testing - @ResourceComponentInstances annotation that is similar to the "@DiscoveredResources" from the previous examples but provides the actual resource components instead of just the resources.

There is also a way of manually deploying stuff into the plugin container as well as manually start and stop the whole PC - interestingly, this is provided by Arquillian itself.

The plugin container inside these tests runs by default in the embedded mode. It is possible to reconfigure it (in arquillian.xml file that provides bootstrap config for arquillian containers) though there is not yet an easy way of configuring the PC to use specific server-services (i.e. a mocked-out RHQ server that we sometimes use in our tests).

The code for all this is for now in a feature branch, because I want to do some more experiments/stabilization on it before it goes to master.

You can checkout the "feature/arquillian-integration" branch to see the code in "modules/arquillian-integration".

For a slightly more elaborate test that shows all the features currently available, you can see the RhqAgentPluginContainerTest in the modules/arquillian-integration/container" module (http://git.fedorahosted.org/git/?p=rhq/rhq.git;a=blob;f=modules/arquillian-integration/container/src/test/java/org/rhq/test/arquillian/RhqAgentPluginContainerTest.java;h=d79033593f3d692ed0d1f4f010a9e1e6f5f09a87;hb=3e5ae62322a826c9570e534987aa4f72255fb871).

Ideas for making this better or cover even more ground while testing our plugins are more than welcome.

Lukas



More information about the rhq-devel mailing list