Tuesday, November 11, 2008

maven-junit4osgi-plugin

Update: the junit4osgi artifact has recently changed. The groupID became org.apache.felix. Moreover, the plugin is now in the iPOJO trunk.

In my last post, I explain the advantages of integrating integration test in the build process. However, such tools was inexistent until … now ☺

As I explained, the junit4osgi framework allows testing an OSGi applications with a "junit++" framework (i.e. an adapted junit distribution providing useful methods to handle easily OSGi specific features such as services).

But, the junit4osgi framework is a “standalone” framework and is not integrated in a build tools such as Ant or Maven. This post describes a maven plug-in, maven-junit4osgi-plugin, executing tests in a maven-based build process.

Constraints of such tools
Providing such front-end is useful but should meet some requirements:
Tests are executed “in container”. So, tested bundles are really deployed on an OSGi framework (I choose Apache Felix). So tests are executing in an execution environment close to the final (production) execution environment. The goal of integration tests is to test the application in a production-like environment.
  • The project under construction is not a functional bundle, but can either be empty or contain integration tests. Integration tests are not placed in the same project as the project under test. Integration tests are packaged inside others bundles deployed on the same framework as the application under test..
  • To recreate the “final” execution environment, several bundles can be required (technical services, the application under test…). So the plug-in must support the deployment of required bundles.
  • Test results must be reported to the user. Maven provides an infrastructure to create web site. Moreover, Surefire (the Maven “regular” test plug-in) provides a plug-in generating a web page with test result. The provided plug-in should provide the same features and should reuse the same format as Surefire.
The good news is that the provided plug-in, maven-junit4osgi-plugin, match these requirements!

What does the maven-junit4osgi-plugin provide?
  • Allows testing OSGi applications
  • Integrated in a Maven-based build process
  • Provides the same output as Surefire
  • Supports Maven site generation
Using the plug-in

Download and building the plug-in
The plug-in sources are available in the iPOJO trunk.
However the junit4osgi and iPOJO runtime are also required. So, download the source of iPOJO:
svn co http://svn.apache.org/repos/asf/felix/trunk/ipojo/
To compile it, run the following commands:
cd ipojo
mvn clean install –Pexamples
(the –Pexamples allows compiling iPOJO examples and so the junit4osgi framework ans the plug-in). Now you can use the plug-in in your project.

Simple configuration
So, first the project using the plug-in is not the project under test. It’s another project containing either only integration-test packaged in a bundle, or is empty (and so depends on other bundles containing integration tests).
Tests contained in the project are developed with junit4osgi, and are packaged in a bundle with the maven-bundle-plugin.
In the pom file, add the following plugin configuration to use the maven-junit4osgi-plugin:

<plugin>
<groupid>org.apache.felix</groupid>
<artifactid>maven-junit4osgi-plugin</artifactid>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
<configuration>
<deployprojectartifact>true</deployprojectartifact>
</configuration>
</execution>
</executions>
</plugin>

Plugin parameter
The plug-in has only one parameter. The 'deployProjectArtifact' parameter enables or disables the current artifact deployment. If the current project contains tests, the plug-in can deploy the built artifact (as illustrated in this pom). Otherwise, the current project artifact is not deployed. This can be useful if the project just depends on other test bundles and sets the test configuration (as this pom).

Configuring the set of bundles to deploy

There is two different ways to configure the plug-in to deploy other bundles. If the bundle to deploy is a maven artifact, just add this artifact as a maven project dependency and set the dependency scope to ‘test’. Here is an example:

<dependency>
<artifactid>tests.manipulation.metadata</artifactid>
<groupid>ipojo.tests</groupid>
<version>1.1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>

If your bundle is not a maven artifact, you can configure the plugin with the bundle URL (from where the bundle will be deployed)

<configuration>
<deployprojectartifact>true</deployprojectartifact>
<bundles>
<param>file:/Users/clement/bundles/test-metadata.jar</param>
</bundles>
</configuration>


Set bundles are installed and started. You can depend on bundle that does not contain test as well as bundle containing tests.

Executing the plug-in

To execute test, just launch the ‘mvn clean integration-test’ command.

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building iPOJO Primitive Manipulation Test Suite
[INFO] task-segment: [integration-test]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [bundle:bundle]
[INFO] [ipojo:ipojo-bundle {execution: default}]
[INFO] Start bundle manipulation
[INFO] Metadata file : /Users/clement/Documents/workspaces/felix-trunk/ipojo/tests/manipulator/primitives/target/classes/metadata.xml
[INFO] Input Bundle File : /Users/clement/Documents/workspaces/felix-trunk/ipojo/tests/manipulator/primitives/target/tests.manipulation.primitives-1.1.0-SNAPSHOT.jar
[INFO] Bundle manipulation - SUCCESS
[INFO] [junit4osgi:test {execution: default}]
Analyzing org.apache.felix.ipojo - compile
Analyzing org.apache.felix.ipojo.metadata - compile
Analyzing org.osgi.core - compile
Analyzing junit - compile
Analyzing org.apache.felix.ipojo.junit4osgi - compile
Analyzing tests.manipulation.metadata - test

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Deploy : /Users/clement/Documents/workspaces/felix-trunk/ipojo/tests/manipulator/primitives/target/tests.manipulation.primitives-1.1.0-SNAPSHOT.jar
Loading org.apache.felix.ipojo.test.scenarios.manipulation.ManipulationTestSuite
Loading org.apache.felix.ipojo.test.scenarios.manipulation.ManipulationTestSuite
Junit Extender starting ...
Running Manipulation Metadata Test Suite
Tests run: 16, Failures: 0, Errors: 0, Time elapsed: 0 sec
Running Primitive Manipulation Test Suite
Tests run: 17, Failures: 0, Errors: 0, Time elapsed: 0 sec

Results :

Tests run: 33, Failures: 0, Errors:0

Unload test suites [class org.apache.felix.ipojo.test.scenarios.manipulation.ManipulationTestSuite]
Unload test suites [class org.apache.felix.ipojo.test.scenarios.manipulation.ManipulationTestSuite]
Cleaning test suites ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6 seconds
[INFO] Finished at: Mon Nov 10 21:30:21 CET 2008
[INFO] Final Memory: 9M/18M
[INFO] ------------------------------------------------------------------------

Failures and errors are reported in the plugin output.

Generating the report web page
When test are executed, the plug-in generates XML reports (int the target/junit4osgi-reports directory) using the same convention as Surefire. So, it is possible to configure Surefire to generate the web page with test results.
To do this, add the following report configuration to the project executing tests:

<reporting>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-surefire-report-plugin</artifactid>
<version>2.4.3</version>
<configuration>
<showsuccess>true</showsuccess>
<reportsdirectories>
<param>target/junit4osgi-reports</param>
</reportsdirectories>
</configuration>
</plugin>
</plugins>
</reporting>
This snippet configures the maven-surefire-report-plugin to collect results from the ‘target/junit4osgi-reports’ directory.
Then execute the plugin with the following command:
mvn org.apache.maven.plugins:maven-surefire-report-plugin:2.4.3:report

This command generates the web page with test results in ‘target/site’. This page shows an example of page generated with this command.

Plug-in design
The plug-in is quiet simple, it just starts an embedded Felix with a special activator installing and starting the junit4osgi framework and specified bundles.

Then, before executing test, the plug-in waits for “stability”. Indeed, as bundle activation can be asynchronous, the plug-in need to wait that the configuration is stable. Stability is obtained when all bundles are activated, and no new services appear or disappear on a 500 ms period. If after several second the stability cannot be reached, the plug-in stops.

Once the stability is reached, the junit4ogsi runner service is used to execute tests. Then results are collected and reports are generated.

Conclusion
This post has presented a front-end automating the execution of junit4osgi tests. Now it is possible to integrate OSGi application tests in a build process. The presented maven plugin provides following features:
  • An easy integration in a Maven-based build process
  • A good flexibility allowing reproducing production execution environments to test the application
  • Test result output is the same as surefire
  • Is able to generate Surefire-like reports

4 comments:

David Illsley said...

I've been playing with the plugin (for Apache Axiom) and it does exactly what I want. Is there an ETA on when it'll be available from a maven repo (SNAPSHOT is ok)?
Cheers,
David'

Clement said...

Hi,

I just deployed snapshots from the junit4osgi framework (and so, from the plugin) on the Apache Snapshot Repository (http://people.apache.org/maven-snapshot-repository/org/apache/felix/maven-junit4osgi-plugin/1.1.0-SNAPSHOT/).

An official release is planned too. I'm moving forward the iPOJO 1.2.0 release. Then I will release the junit4osgi framework.

Cheers,

Clement

David Illsley said...

Thanks for that, and 1.2.0 sounds good too, but when I try to use the SNAPSHOT with a clean local repository I get:

Missing:
----------
1) org.apache.felix:org.apache.felix.ipojo.handler.extender:jar:1.1.0-SNAPSHOT

...

Path to dependency:
1) org.apache.felix:maven-junit4osgi-plugin:maven-plugin:1.1.0-SNAPSHOT
2) org.apache.felix:org.apache.felix.ipojo.handler.extender:jar:1.1.0-SNAPSHOT

Any chance you could upload that SNAPSHOT too?
Thanks,
David

Clement said...

Hi,

Oups, I was sure to already deployed iPOJO artifacts. So, I fix the issue. I tried to execute test from scratch (empty maven repository) with the Apache snapshot repository. So, you should be able to execute it now.

Cheers,

Clement