blob: faeb3bfc51f25ab0b88250aea3576155c00edb5c [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chapter&nbsp;12.&nbsp;Testing OSGi based Applications</title><link rel="stylesheet" href="css/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"><link rel="start" href="index.html" title="Eclipse Gemini Blueprint Reference Guide"><link rel="up" href="reference.html" title="Part&nbsp;II.&nbsp;Reference Documentation"><link rel="prev" href="compendium.html" title="Chapter&nbsp;11.&nbsp;Compendium Services"><link rel="next" href="resources.html" title="Part&nbsp;III.&nbsp;Other Resources"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="testing"></a>Chapter&nbsp;12.&nbsp;Testing OSGi based Applications</h2></div></div></div><p>By following best practices and using the Gemini Blueprint
support, your bean classes should be easy to unit test as they will have
no hard dependencies on OSGi, and the few OSGi APIs that you may interact
with (such as <code class="interfacename">BundleContext</code>) are interface-based
and easy to mock. Whether you want to do unit testing or <a xmlns:xlink="http://www.w3.org/1999/xlink" href="http://en.wikipedia.org/wiki/Integration_testing" target="_top">
integration</a> testing, Spring DM can ease your task.</p><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="testing:mocks"></a>12.1.&nbsp;OSGi Mocks</h2></div></div></div><div class="sidebar"><p class="title"><b>Mocks vs Stubs</b></p><p>There are various strategies to unit test code
that requires collaborators. The two most popular strategies
are <span class="emphasis"><em>stubs</em></span> and <span class="emphasis"><em>mocks</em></span>.
</p><p>
See <a xmlns:xlink="http://www.w3.org/1999/xlink" href="http://martinfowler.com/articles/mocksArentStubs.html" target="_top">
this</a> article by Martin Fowler which describes in detail the difference
between them.</p></div><p>
Even though most OSGi API are interfaces and creating mocks using a specialized
library like <a xmlns:xlink="http://www.w3.org/1999/xlink" href="http://www.easymock.org/" target="_top">EasyMock</a> is fairly
simple, in practice the amount of code of setting the code (especially on JDK 1.4)
becomes cumbersome. To keep the tests short and concise, Gemini Blueprint/Spring DM provides OSGi
mocks under <code class="literal">org.eclipse.gemini.blueprint.mock</code> package.</p><p>It's up to you to decide whether they are useful or not however, we make extensive
use of them inside Gemini Blueprint/Spring DM test suite. Below you can find a code snippet that you
are likely to encounter in our code base:</p><pre class="programlisting"><span class="hl-keyword">private</span> ServiceReference reference;
<span class="hl-keyword">private</span> BundleContext bundleContext;
<span class="hl-keyword">private</span> Object service;
<span class="hl-keyword">protected</span> <span class="hl-keyword">void</span> setUp() <span class="hl-keyword">throws</span> Exception {
reference = <span class="hl-keyword">new</span> MockServiceReference();
bundleContext = <span class="hl-keyword">new</span> MockBundleContext() {
<span class="hl-keyword">public</span> ServiceReference getServiceReference(String clazz) {
<span class="hl-keyword">return</span> reference;
}
<span class="hl-keyword">public</span> ServiceReference[] getServiceReferences(String clazz, String filter)
<span class="hl-keyword">throws</span> InvalidSyntaxException {
<span class="hl-keyword">return</span> <span class="hl-keyword">new</span> ServiceReference[] { reference };
}
<span class="hl-keyword">public</span> Object getService(ServiceReference ref) {
<span class="hl-keyword">if</span> (reference == ref)
<span class="hl-keyword">return</span> service;
<span class="hl-keyword">super</span>.getService(ref);
}
};
...
}
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> testComponent() <span class="hl-keyword">throws</span> Exception {
OsgiComponent comp = <span class="hl-keyword">new</span> OsgiComponent(bundleContext);
assertSame(reference, comp.getReference());
assertSame(object, comp.getTarget());
}</pre><p>As ending words, experiment with them and choose whatever style or library you feel most confortable with.
In our test suite we use the aforementioned mocks, EasyMock library and plenty of integration testing (see below).</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="testing:integration"></a>12.2.&nbsp;Integration Testing</h2></div></div></div><div class="sidebar"><p class="title"><b>What about JUnit4/TestNG?</b></p><p>While JUnit4/TestNG overcome the class inheritance
problem that appears when building base JUnit classes, by decoupling
the runner from the test through annotations, Gemini Blueprint/Spring DM cannot use
them since it has to support Java 1.4.</p><p>However, it is planned for the future to provide an optional,
JVM 5-based testing extension to integrate the existing testing framework
with the aforementioned libraries.
</p></div><p>In a restricted environment such as OSGi, it's important to test the visibility and versioning of your classes,
the manifests or how your bundles interact with each other (just to name a few).</p><p> To ease integration testing, the Gemini Blueprint project provides a test class hierarchy
(based on <code class="classname">org.eclipse.gemini.blueprint.test.AbstractOsgiTests</code>) that
provides support for writing regular <code class="literal">JUnit</code> test cases that are then
automatically executed in an OSGi environment.</p><p>In general, the scenario supported by Gemini Blueprint/Spring DM testing framework is:</p><div class="itemizedlist"><ul type="disc"><li><p>start the OSGi framework (Equinox, Knopflerfish, Felix)</p></li><li><p>install and start any specified bundles required for the
test</p></li><li><p>package the test case itself into a <code class="literal">on the fly</code> bundle,
generate the manifest (if none is provided) and install it in the OSGi
framework</p></li><li><p>execute the test case inside the OSGi framework</p></li><li><p>shut down the framework</p></li><li><p>passes the test results back to the originating test case
instance that is running outside of OSGi</p></li></ul></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/admons/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top">The testing framework is aimed at running OSGi integration tests from a non-OSGi environment (like Ant/Maven/IDE). The testing framework
is NOT meant to be used as an OSGi bundle (nor will it work for that matter). In practice this means that the testing bundle should be separate from the bundle(s) it
tests (similar to unit testing, where tests are separate from the classes they test).</td></tr></table></div><p>By following this sequence it is trivial to write JUnit-based
integration tests for OSGi and have them integration into any environment
(IDE, build (ant, maven), etc.) that can work with JUnit.</p><p>The rest of this chapter details (with examples) the features
offered by Gemini Blueprint/Spring DM testing suite.</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:simple-test"></a>12.2.1.&nbsp;Creating A Simple OSGi Integration Test</h3></div></div></div><p>
While the testing framework contains several classes that offer specific
features, it is most likely that your test cases will extend
<code class="classname">org.eclipse.gemini.blueprint.test.AbstractConfigurableBundleCreatorTests</code> (at least
this is what we use in practice).
</p><p>Let's extend this class and interact with the OSGi platform through
the <code class="literal">bundleContext</code> field:</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">class</span> SimpleOsgiTest <span class="hl-keyword">extends</span> AbstractConfigurableBundleCreatorTests {
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> testOsgiPlatformStarts() <span class="hl-keyword">throws</span> Exception {
System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VENDOR));
System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VERSION));
System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT));
}
}</pre><p>Simply execute the test as you normally do with any JUnit test. On Equinox 3.2.x,
the output is similar to:</p><pre class="programlisting">Eclipse
1.3.0
OSGi/Minimum-1.0,OSGi/Minimum-1.1,JRE-1.1,J2SE-1.2,J2SE-1.3,J2SE-1.4}</pre><p class="remark"><i><span class="remark">It is likely that you will see different log statements made by the testing
framework during your own test execution, but these can be disabled as they only have an informative
value and do not affect the actual execution.</span></i></p><p>Note that you did not have to create any bundle, write any MANIFEST or
bother with imports or exports, let alone starting and shutting down the OSGi
platform. The testing framework takes care of these automatically
when the test is executed.</p><p>Let's do some quering and figure out what the environment in which the tests run is.
A simple way to do that is to query the <code class="interfacename">BundleContext</code>
for the installed bundles:</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">void</span> testOsgiEnvironment() <span class="hl-keyword">throws</span> Exception {
Bundle[] bundles = bundleContext.getBundles();
<span class="hl-keyword">for</span> (<span class="hl-keyword">int</span> i = 0; i &lt; bundles.length; i++) {
System.out.print(OsgiStringUtils.nullSafeName(bundles[i]));
System.out.print(<span class="hl-string">", "</span>);
}
System.out.println();
}</pre><p>The output should be similar to:</p><pre class="programlisting">OSGi System Bundle, ObjectWeb ASM, log4j.osgi, spring-test, spring-osgi-test, spring-osgi-core,
spring-aop, spring-osgi-io, slf4j-api,
spring-osgi-extender, etc... TestBundle-testOsgiPlatformStarts-com.your.package.SimpleOsgiTest,
</pre><p>As you can see, the testing framework installs the mandatory requirements required for running the
test such as the Spring, Gemini Blueprint/Spring DM, slf4j jars among others.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:provisioning"></a>12.2.2.&nbsp;Installing Test Prerequisites</h3></div></div></div><div class="sidebar"><p class="title"><b>OSGi-friendly libraries</b></p><p>To work in OSGi environments, jars need to declare in their
<code class="literal">MANIFEST.MF</code>, Export or Import packages; that is
declare what classes they need or offer to other bundles.
Most libraries are OSGi unaware and do not provide the proper manifest
entries which means they are unusable in an OSGi environment.</p><p>At the moment, there are several initiatives in the open source space
to provide the proper manifest - please see the FAQ for more information.
</p></div><p>Besides the Gemini Blueprint/Spring DM jars and the test itself is highly likely that you depend on
several libraries or your own code for the integration test.</p><p>Consider the following test that relies on Apache Commons
<a xmlns:xlink="http://www.w3.org/1999/xlink" href="http://commons.apache.org/lang/" target="_top">Lang</a>:</p><pre class="programlisting"><span class="hl-keyword">import</span> org.apache.commons.lang.time.DateFormatUtils;
...
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> testCommonsLangDateFormat() <span class="hl-keyword">throws</span> Exception {
System.out.println(DateFormatUtils.format(<span class="hl-keyword">new</span> Date(), <span class="hl-string">"HH:mm:ssZZ"</span>));
}
}</pre><p>Running the test however yields an exception:</p><pre class="programlisting">java.lang.IllegalStateException: Unable to dynamically start generated unit test bundle
...
Caused by: org.osgi.framework.BundleException: The bundle could not be resolved.
Reason: Missing Constraint: Import-Package: org.apache.commons.lang.time; version="0.0.0"
...
... 15 more
</pre><p>The test requires <code class="literal">org.apache.commons.lang.time</code> package but there is no bundle
that exports it. Let's fix this by installing a commons-lang bundle (make sure you use at least version 2.4
which adds the proper OSGi entries to the jar manifest).</p><p>One can specify the bundles that she wants
to be installed using <code class="literal">getTestBundlesNames</code> or <code class="literal">getTestBundles
</code> method. The first one returns an array of String that indicate the bundle
name, package and versioning through as a String while the latter returns an array of
<code class="literal">Resource</code>s that can be used directly for installing the bundles.
That is, use <code class="literal">getTestBundlesNames</code> when you rely on somebody else to locate
(the most common case) the bundles and <code class="literal">getTestBundles</code> when you want to
locate the bundles yourself.
</p><p>By default, the test suite performs a lookup for artifacts, similar to the one used by
<a xmlns:xlink="http://www.w3.org/1999/xlink" href="http://maven.apache.org" target="_top">Maven2</a>, searching first the items as being relative to the
current project and then falling back to the local repository.
The locator expects the bundle String to be a comma separated values containing the artifact group, name, version and (optionally) type.
It's likely that in the future, various other locators will be available. One can plug in their own
locator through the <code class="interfacename">org.eclipse.gemini.blueprint.test.provisioning.ArtifactLocator</code> interface.
</p><p>Let's fix our integration test by installing the required bundle (and some extra osgi libraries):</p><pre class="programlisting"><span class="hl-keyword">protected</span> String[] getTestBundlesNames() {
<span class="hl-keyword">return</span> <span class="hl-keyword">new</span> String[] {
<span class="hl-string">"javax.transaction, com.springsource.javax.transaction, 1.1.0"</span>,
<span class="hl-string">"commons-lang, commons-lang, 2.4"</span> };
};
}</pre><p>Rerunning the test should show that these bundles are now installed in the OSGi platform.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/admons/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">The artifacts mentioned above have to exist in your local maven repository.</td></tr></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:advanced-topics"></a>12.2.3.&nbsp;Advanced Testing Framework Topics</h3></div></div></div><p>The testing framework allows a lot of customization to be made. This chapter
details some of the existing hooks that you might want to know about. However, these
are advanced topics as they increase the complexity of your test infrastructure.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="testing:integration:customize-manifest"></a>12.2.3.1.&nbsp;Customizing The Test Manifest</h4></div></div></div><p>There are cases where the auto-generated test manifest does not suit the needs of the test.
For example the manifest requires some different headers or a certain package needs to be an optional import.</p><p>
For simple cases, one can work directly with the generated manifest - in the example below, the bundle class path
is being specified:
</p><pre class="programlisting"><span class="hl-keyword">protected</span> Manifest getManifest() {
<span class="hl-comment">// let the testing framework create/load the manifest</span>
Manifest mf = <span class="hl-keyword">super</span>.getManifest();
<span class="hl-comment">// add Bundle-Classpath:</span>
mf.getMainAttributes().putValue(Constants.BUNDLE_CLASSPATH, <span class="hl-string">".,bundleclasspath/simple.jar"</span>);
<span class="hl-keyword">return</span> mf;
}</pre><p>
Another alternative is to provide your own manifest by overriding <code class="literal">getManifestLocations()</code>:</p><pre class="programlisting"><span class="hl-keyword">protected</span> String getManifestLocation() {
<span class="hl-keyword">return</span> <span class="hl-string">"classpath:com/xyz/abc/test/MyTestTest.MF"</span>;
}</pre><p>However each manifest needs the following entry:</p>&#8220;<span class="quote">Bundle-Activator: org.eclipse.gemini.blueprint.test.JUnitTestActivator</span>&#8221;<p>since without it, the testing infrastructure cannot function properly. Also, one needs to
import JUnit, Spring and Gemini Blueprint/Spring DM specific packages used by the base test suite:</p><pre class="programlisting">Import-Package: junit.framework,
org.osgi.framework,
org.apache.commons.logging,
org.springframework.util,
org.eclipse.gemini.blueprint.service,
org.eclipse.gemini.blueprint.util,
org.eclipse.gemini.blueprint.test,
org.springframework.context</pre><p>Failing to import a package used by the test class will cause the test to fail with a
<code class="literal">NoDefClassFoundError</code> error.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="testing:integration:specify-test-jar-content"></a>12.2.3.2.&nbsp;Customizing Test Bundle Content</h4></div></div></div><p>By default, for the on-the-fly bundle, the testing infrastructure uses all the classes, xml and properties files
found under <code class="literal">./target/test-classes</code> folder. This matches the project layout for maven which is used
(at the moment by Gemini Blueprint/Spring DM). These settings can be configured in two ways:</p><div class="orderedlist"><ol type="1"><li><p>programmatically by overriding <code class="classname">AbstractConfigurableBundleCreatorTests</code> <code class="literal">getXXX</code>
methods.</p></li><li><p>declaratively by creating a properties file having a similar name with the test case. For example, test
<code class="literal">com.xyz.MyTest</code> will have the properties file named <code class="literal">com/xyz/MyTest-bundle.properties</code>.
If found, the following properties will be read from the file:</p><div class="table"><a name="integration-test-jar-setting-file"></a><p class="title"><b>Table&nbsp;12.1.&nbsp;Default test jar content settings</b></p><div class="table-contents"><table summary="Default test jar content settings" width="100%" border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Property Name</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td>root.dir</td><td><code class="literal">file:./target/test-classes</code></td><td>the root folder considered as the jar root</td></tr><tr><td>include.patterns</td><td><code class="literal">/**/*.class,/**/*.xml,/**/*.properties</code></td><td>Comma-separated string of Ant-style patterns</td></tr><tr><td>manifest</td><td>(empty)</td><td>manifest location given as a String. By default it's empty meaning the manifest
will be created by the test framework rather then being supplied by the user.</td></tr></tbody></table></div></div><br class="table-break"><p>This option is handy when creating specific tests that need to include certain resources (such as localization files
or images).</p></li></ol></div><p>Please consult <code class="classname">AbstractConfigurableBundleCreatorTests</code> and
<code class="classname">AbstractOnTheFlyBundleCreatorTests</code> tests for more customization hooks.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="testing:integration:understanding-manifest-creator"></a>12.2.3.3.&nbsp;Understanding The <code class="code">MANIFEST.MF</code> Generation</h4></div></div></div><p>A useful feature of the testing framework represents the automatic creation of the test manifest based on the test bundle content. The manifest
creator component uses byte-code analysis to determine the packages imported by the test classes so that it can generate the proper OSGi directives for them.
Since the generated bundle is used for running a test, the creator will use the following assumptions:</p><div class="itemizedlist"><ul type="disc"><li><p>No packages will be exported.</p><p>The <span class="emphasis"><em>on-the-fly</em></span> bundle is used for running a test which
(usually) consumes OSGi packages for its execution. This behaviour can be changed by <a href="testing.html#testing:integration:customize-manifest" title="12.2.3.1.&nbsp;Customizing The Test Manifest">customizing</a>
the manifest.</p></li><li><p>Split packages (i.e. classes from the same package can come from different bundles) are not supported.</p><p>
This means that packages present in the test framework are considered complete and no <code class="code">Import-Package</code> entry will be generated for them.
To avoid this problem, consider using sub-packages or moving the classes inside one bundle. Note that split packages are discouraged due to the
issues associated with them (see the OSGi Core spec, Chapter 3.13 - Required Bundles).</p></li><li><p>The test bundle contains only test classes.</p><p>The byte-code parser will look only at the test classes hierarchy. Any other class included in the bundle, will not be considered so no imports
will be generated for it. To change the default behaviour, override <code class="methodname">createManifestOnlyFromTestClass</code> to return
<code class="literal">false</code>:</p><pre class="programlisting"><span class="hl-keyword">protected</span> <span class="hl-keyword">boolean</span> createManifestOnlyFromTestClass() {
<span class="hl-keyword">return</span> false;
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/admons/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">The time required to generate the manifest might increase depending on the number and size of classes in the bundle.</td></tr></table></div><p>
Additionally consider customizing the manifest yourself or attaching the extra code as inner classes to the test class (so it gets parsed automatically).</p></li></ul></div><p>
The reason behind <span class="emphasis"><em>the lack of such features</em></span> is the byte-code parser is aimed to be simple and fast at creating test manifests -
it is not meant as a general-purpose tool for creating OSGi artifacts.
</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:appContext"></a>12.2.4.&nbsp;Creating An OSGi Application Context</h3></div></div></div><p>Gemini Blueprint/Spring DM testing suite builds on top of Spring testing classes. To create an application context
(OSGi specific), one should just override <code class="literal">getConfigLocations[]</code> method and indicate
the location of the application context configuration. At runtime, an OSGi application context will be created
and cached for the lifetime of the test case.</p><pre class="programlisting"><span class="hl-keyword">protected</span> String[] getConfigLocations() {
<span class="hl-keyword">return</span> <span class="hl-keyword">new</span> String[] { <span class="hl-string">"/com/xyz/abc/test/MyTestContext.xml"</span> };
}</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:specify-platform"></a>12.2.5.&nbsp;Specifying The OSGi Platform To Use</h3></div></div></div><p>The testing framework supports out of the box, three OSGi 4.0 implementations namely:
Equinox, Knopflerfish and Felix. To be used, these should be in the test classpath. By default,
the testing framework will try to use Equinox platform. This can be configured in several ways:</p><div class="orderedlist"><ol type="1"><li><p>programmatically through <code class="literal">getPlatformName()</code> method</p>.
<p>Override the aforementioned method and indicate the fully qualified name of
the <code class="interfacename">Platform</code> interface implementation. Users can use the <code class="classname">Platforms</code>
class to specify one of the supported platforms:</p><pre class="programlisting"><span class="hl-keyword">protected</span> String getPlatformName() {
<span class="hl-keyword">return</span> Platforms.FELIX;
}</pre></li><li><p>declaratively
through <code class="literal">org.eclipse.gemini.blueprint.test.framework</code> system property.</p><p>If this property is set,
the testing framework will use its value as a fully qualified name of a Platform implementation.
It that fails, it will fall back to Equinox after logging a warning message.
This option is useful for building tools (such as ant or maven) since it indicates a certain
target environment without changing and test code.</p></li></ol></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:specify-test-wait-time"></a>12.2.6.&nbsp;Waiting For The Test Dependencies</h3></div></div></div><p>A built-in feature of the testing framework is the ability to wait until all dependencies are deployed before
starting the test execution. Since the OSGi platforms are concurrent by nature, installing a bundle doesn't mean that
all its services are running. By running a test before its dependency services are fully initialized can cause sporadic
errors that pollute the test results. By default, the testing framework inspects all bundles installed by the user and,
if they are Spring-powered bundles, waits until they are fully started (that is their application context is published
as an OSGi service). This behaviour can be disabled by overriding <code class="literal">shouldWaitForSpringBundlesContextCreation</code>
method. Consult <code class="classname">AbstractSynchronizedOsgiTests</code> for more details.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="testing:integration:performance"></a>12.2.7.&nbsp;Testing Framework Performance</h3></div></div></div><p>Considering all the functionality offered by the testing framework, one might wonder if this doesn't become a
performance bottleneck. First, it's worth noting that all the work done automatically by the testing infrastructure
has to be done anyway (such as creating the manifest or creating a bundle for the test or installing the bundles).
Doing it manually simply does not work as it's too error prone and time consuming.
In fact, the current infrastructure started as way to do efficient, automatic testing without worrying
about deployment problems and redundancy.</p><p>As for the numbers, the current infrastructure has been used internally for the last half a year - our integration tests
(around 120) run in about 3:30 minutes on a laptop. Most of this time is spent on starting and stopping the OSGi platform: the "testing
framework" takes around 10% (as shown in our profiling so far).
For example, the manifest generation has proved to take less then 0.5 seconds in general, while the jar creation around 1
second.</p><p>However, we are working on making it even faster and smarter so that less configuration options are needed and
the contextual information available in your tests is used as much as possible. If you have any ideas or suggestion,
feel free to use our issue tracker or/and forum.
</p></div><p>Hopefully this chapter showed how Gemini Blueprint/Spring DM testing infrastructure can simplify OSGi integration testing and
how it can be customized. Consider consulting the javadocs for more information.
</p></div></div><div xmlns:fo="http://www.w3.org/1999/XSL/Format" class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="compendium.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="resources.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;11.&nbsp;Compendium Services&nbsp;</td><td width="20%" align="center"><span style="color:white;font-size:90%;"><a href="http://www.SpringSource.com/" title="SpringSource - Spring from the Source">Sponsored by SpringSource
</a></span></td><td width="40%" align="right" valign="top">&nbsp;Part&nbsp;III.&nbsp;Other Resources</td></tr></table></div></body></html>