What's the best way to balance declared exports of packages from a bundle and the requirements of unit testing?
Consider a bundle 'mybundle' for which you want to write unit tests. The bundle's source is stored in an IDE's 'project' concept. For instance:
mybundle
src/java
mybundle.package1
...java
bnd.bnd
By unit tests I mean tests of individual POJOs, irrelevant to the wider OSGi context in which these classes may be used within a bundle. Where possible, the tests should be runnable with 'vanilla' classloading, such as by the JUnit runner in Eclipse.
At development time, here are a few ways of packaging the unit tests:
Unit tests in the bundle source
Here, the unit tests are added to a source folder in the project:
mybundle
src/java
mybundle.package1
...java
test/java
mybundle.package1.test
...java
bnd.bnd
Note the appended '.test' to differentiate packages and avoid split package problems.
Typically there will be some measure to ensure test classes don't end up in the built bundle JAR.
Unit tests in a separate bundle
Here a separate bundle is added, name suffixed with '.test' as is the general convention.
mybundle
src/java
mybundle.package1
...java
mybundle.test
test/java
mybundle.package1.test
...java
bnd.bnd
The trouble with this is that because the classes are separated, and the running of unit tests may not be knowledgeable of the OSGi environment (e.g. using the Eclipse JUnit runner) you will have to decorate the runtime classpath of the JUnit runner.
Unit tests in a fragment
(Thanks @HollyCummins). Here a separate bundle fragment is created:
mybundle.fragment
test/java
mybundle.package1.test
...java
bnd.bnd
The fragment declares 'mybundle' as its host, thus allowing it to share the classes in 'mybundle' without the need of the packages being exported.
The disadvantage of this is that because fragment loading is an OSGi concept, you need to run with an OSGi container or decorate the classpath.
Export problems
The problem comes when considering how bundles perform Export-Package. It is considered good practice to export as few packages as possible. And yet it seems that unit testing forces extra packages to be exported.
This is most obvious for the second option, having a separate testing bundle. The tests in the testing bundle must Import-Package the classes under test, and the bundle under test must also Export-Package all said classes under test.
So the obvious solution is to lean toward having unit tests in the bundle source, but problems soon crop up in non-trivial situations. You may want to share testing code, for instance you might have OSGi integration tests in a separate bundle. To share code you end up having to Export-Package the testing packages, and then of course you also end up with testing code in the built bundle!
What is the best way to organise OSGi bundles/projects for testing?