After developing a component of our OSGI application, we aim to test the new funcionality functionality before integrating it. Unitary tests are a good solution to check the classes of our bundle in an isolated way, but what if we want to test how our bundle fits with the other components of our application? Well, we need a testing toolkit providing us the availibity of emulating our deployes deployment environment, like Pax-Exam.
...
Pax-Exam is an automated testing framework for OSGI applications. Its main particularity is how it works. Pax-Exam starts a an OSGI container, install the bundles we configure in installs bundles into it, and run runs our test classes. This methodology allows us to make assertions over many components, like the services we publish or the result of an operation.
Integration test In tests in OpenNaaS are developed using Pax-Exam 2.3.0. Using configuration options provided by this technology, we deploy our own platform inside the OSGI container, automating the installation of bundles and additional features.
...
An integration test is just no more than a java class with some particular annotations and methods. First of all, we have to define the driver the test will run with (in our case, JUnit driver), using the @RunWith the @RunWith annotation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@RunWith(JUnit4TestRunner.class) public abstract class OSPFIntegrationTest { ... } |
...
As an optional parameter you can also define the reactor strategy. It determinates the behaviour of the container between test tests of the same and class, but also of the rest of the classes. Available options are "AllConfinedStagedReactorFactory" (a new test container will be started and stoped for each test) and "EagerSingleStagedReactorFactory" (all configured test containers are stated before starting the first test). Default strategy is "AllConfinedStagedReactorFactory". This attribute can be confifured configured by the @ExamReactorStrategy the @ExamReactorStrategy annotation.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@RunWith(JUnit4TestRunner.class) @ExamReactorStrategy(AllConfinedStagedReactorFactory.class) public abstract class OSPFIntegrationTest { ... } |
...
In order to configure the main attributes of the OSGI container, Pax-Exam provides multiple configuration mechanisms, like the classpath, JVM configuration options, framework selection, etc. Just to simplify the development of new tests, OpenNaaSs contain a helper class you can use from any integration test. The most important methods are:
...
All this options must be defined in a method annotated with @Configuration and a @Configuration annotated method and returning the type Option[] type.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@Configuration public static Option[] configuration() { return options(opennaasDistributionConfiguration(), includeFeatures("opennaas-router", "opennaas-junos"), noConsole(), keepRuntimeFolder()); } |
As an example, we can see how opennaas-router and opennaas-junos features are included to run the tests of this class.
Writing our test class
Dependency Injection
Pax-Exam allows the injection of dependencies inside the test class directly from the OSGI service registrry. It provides two ways to do it: either using the javax.inject.Inject annotation or optional @Filter optional @Filter one using the BundleContext API.
...
The example above illustrates both possibilities. First of all we inject the ResourceManager, the ProtocolManager and the BundleContext using the java.inject.Inject annotation. On the other hand, using the @Filter the @Filter Pax-Exam looks in the OSGI service registry the service identified by the given type and also the given attribute value. RouterRepository service Router Repository service and Netconf service are retrieved using the name of the its blueprint container.
...
A simple class can contain multiple test. Tests are no more than methods annotated with the @Test the @Test annotation. After configurint configuring and starting the OSGI container, Pax-Exam will scan the class looking for all the annotated functions and will run them according to the reactor strategy we have set.
...
The test checks if after starting a resource, it contains at least one capability (startResource() adds the OSPF and Queue capabilities) and that after stopping the resource it has been successfully removed from the ResourceManager service service.
As in unitary tests, you can take advantage of the @Before the @Before and @After annotation. Functions with these annotations will be called before/after executing the integration test in order to prepare the test environment or to check the state of the container after them.
Debugging your test
Pax-Exam provides configuration options to pass arguments to the JVM that will be started. We can take advantage of it to debug our test. In OpenNaaS we have created a helper method that will take care of it.
...
Bassicaly, this function opens a debug socket in port 5005. You can connect your Eclipse (or another IDE) configuring the address and the port of the remove java application.
Maven
...
dependencies
Integration tests in OpenNaaS are located under /itests/ folder. Therefore they inherit from it all the necessary dependencies for starting and configuring the OSGI container.
...
So, the only dependencies we have to define in our pom are the ones containing the componentes components we want to check. OSGF integration tests require OpenNaaS core , due it contains ResourceManager and and ResourceRepository; the Router Repository to add and remove routers, the Router Model to make assertions over it, and also the capabilities and actionsets actionset to test the OSPF developed funcionality.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<dependencies> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.core.resources</artifactId> </dependency> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.extensions.router.repository</artifactId> </dependency> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.extensions.router.model</artifactId> </dependency> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.extensions.queuemanager</artifactId> </dependency> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.extensions.router.capability</artifactId> </dependency> <dependency> <groupId>org.opennaas</groupId> <artifactId>org.opennaas.extensions.router.actionsets.junos</artifactId> </dependency> <dependency> <groupId>org.opennaas.itests</groupId> <artifactId>org.opennaas.itests.helpers</artifactId> </dependency> <dependency> <groupId>net.i2cat.netconf</groupId> <artifactId>netconf4j</artifactId> </dependency> </dependencies> |
Pax-Exam Containers
Even thought though in OpenNaaS we deploy our platform to run the tests, Pax-Exam 2.x provides three different OSGI containers in which you can launch an OSGI framework and install bundles. Native Container is launched in the same JVM as the driver, and Forked Container launch the framework in an isolated JVM. The third option is the Pax Runner Container. As the forked container, the framework is launched in a separrate VM, but it uses Pax Runner as the main tool to configure and run the tests. The list of maven dependencies you must include in your pom file is defined in the Pax-Exam wiki.
Container Configuration
As seen in OpenNaaS example, we can configure the containter Pax-Exam will provide to test our application. In this section we will explain the main additional options.
...
Sometimes, one of our bundles needs to import a package no not exported by default by the JVM. Pax-Exam lets you configure a list of additional packages you want the system bundle to export.
...
Additional configuration options.
You can find the rest complete list of configuration options in Pax-Exam wiki.
...