<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The moons of Verthandi - Blog by Dani Giribet &#187; unit testing</title>
	<atom:link href="http://dani.calidos.com/tag/unit-testing/feed/" rel="self" type="application/rss+xml" />
	<link>http://dani.calidos.com</link>
	<description></description>
	<lastBuildDate>Wed, 16 Jun 2010 19:38:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Components on the server (6): adding Integration Testing</title>
		<link>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/</link>
		<comments>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/#comments</comments>
		<pubDate>Fri, 07 May 2010 19:59:48 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=265</guid>
		<description><![CDATA[In this installment of the server-side OSGi series, we add integration testing capabilities to our project. Integration testing goes beyond plain unit testing and checks the interactions between real components. This is in contrast with unit testing, which generally uses mockups to represent components outside the one being tested. Please take a look at previous [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the server-side OSGi series, we add integration testing capabilities to our project. Integration testing goes beyond plain unit testing and checks the interactions between real components. This is in contrast with unit testing, which generally uses mockups to represent components outside the one being tested. Please take a look at previous installments, as usual.</p>
<p>In the case of integration testing, it is manly used in a pre-production environment, with a valid build that has all unit tests passed. It can even be used in production to just after a deployment is made, taking care not to have destructive checks or massive load tests in the integration test code. YMMV.</p>
<p>To achieve integration testing we need to check the various OSGi components deployed interact in the way that is expected of them. Therefore we need to test the components in a group and not in isolation. To do that in the OSGi world means we need to have access to the OSGi context from within the tests to access services, call them and check their responses, etc.</p>
<p>To allow for this kind of integration testing within the OSGi environment, we make a slight modification to the excellent test.extender we have already patched in the previous installment.</p>
<p>Basically, the basic test.extender seeks out any JUnit test classes within the fragment bundle, creates an instance using an empty constructor and then fires up the tests. This is activated either by default when the fragment is loaded or by using &#8216;test <bundleid>&#8216; in the console. For further information please see the <a href="http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/">previous post</a> about this subject.</p>
<p>For our integration testing, we add an extra command to test.extender:</p>
<pre class="java:nocontrols:nogutter">
public Object _integrationTest(CommandInterpreter intp) {
        String nextArgument = intp.nextArgument();
    	testExtender.integrationTest(Long.parseLong(nextArgument));
    	return null;
}
</pre>
<p>And we refactor the TestExtender to add the integrationTest method which reuses some of the code to instantiate test cases using a constructor that accepts the OSGi context as a parameter.</p>
<pre class="java:nocontrols:nogutter">
Constructor<?>[] constructors = clazz.getConstructors();
boolean foundConstructor = false;
for (int i = 0; i < constructors.length &#038;&#038; !foundConstructor; i++) {
	Constructor<?> constructor = constructors[i];
	Class<?>[] types = constructor.getParameterTypes();
	if (types.length==1 &#038;&#038; types[0].isInstance(context)) {
		foundConstructor = true;
		EClassUtils.testClass(inspectClass, constructor.newInstance(context));
	}
} // for
</pre>
<p>The OSGi context is passed onto the constructor and then the test class is run. It is obviously up to the test class to use the context appropriately for its integration testing.</p>
<p>In our cache project setup, we can do some useful integration testing on the cache.controller component, basically checking if the interaction with the provider components is behaving as we expect it. The integration testing is also added to a fragment that can be deployed optionally, of course.</p>
<p>We start by creating the fragment and adding a testing class like this:</p>
<p><img alt="Adding test class" src="http://dani.calidos.com/img/2010/osgi-06/junit-test-case.png" title="Adding test class" class="alignnone" width="472" height="540" /></p>
<p>Next, we add the constructor that accepts an OSGi context, which is very simple:</p>
<pre class="java:nocontrols:nogutter">
public CacheIntegrationTest(BundleContext ctx) {
	super();
	this.context = ctx;
}
</pre>
<p>In the setup and teardown methods we get and unget the cache service to perform the testing:</p>
<pre class="java:nocontrols:nogutter">

public void setUp() throws Exception {
	serviceReference = context.getServiceReference(Cache.class.getName());
	controller = (CacheControllerCore) context.getService(serviceReference);

}

public void tearDown() throws Exception {
	context.ungetService(serviceReference);
	controller = null;
}
</pre>
<p>In this case we get the controller cache service and store it in an instance used to perform the tests. This is quite simple and fulfills our intended purpose but we still have the flexibility to make more complex integration testing if needed.</p>
<p>Next we create as many test cases as needed:</p>
<pre class="java:nocontrols:nogutter">
public void testGet() {
	try {
		controller.init();
		double v = Math.random();
		String k = "/k"+v;
		controller.set(k, v);
		assertEquals(v, controller.get(k));
	} catch (CacheProviderException e) {
		e.printStackTrace();
		fail(e.getMessage());
	}

}
</pre>
<p>It should be noted that while the code looks like regular testing code, it is actually using real services from the OSGi environment as opposed to mockups. This means we are testing the real integration between components as well as the individual controller component code. The disadvantage here is that if there is an error in the controller we might mistake the problem with an issue with the services used. In conclusion, having integration code doesn&#8217;t negate the need to have unit tests.</p>
<p>Once we load the fragment onto the environment, first we need to obtain the bundle id of the integration fragment and then launch the integration testing in this manner:</p>
<p><code><br />
osgi> integrate 125<br />
Bundle : [125] : com.calidos.dani.osgi.cache.controller.integration<br />
_<br />
CLASS : [com.calidos.dani.osgi.cache.controller.CacheIntegrationTest]<br />
___________________________________________________________________________<br />
Method : [ testInit ] PASS<br />
Method : [ testInitInt ] PASS<br />
Method : [ testSize ] PASS<br />
14:21:43,077 WARN  CacheControllerCore Couldn't clear some of the provider caches as operation is unsupported<br />
14:21:43,077 WARN  CacheControllerCore Couldn't clear some of the provider caches as operation is unsupported<br />
Method : [ testClear ] PASS<br />
Method : [ testSet ] PASS<br />
Method : [ testGet ] PASS<br />
Method : [ testGetStatus ] PASS<br />
___________________________________________________________________________<br />
</code></p>
<p>The results tell us that all operations are OK but we need to bear in mind that the clear operation is not supported in some backend caches. If this is what is expected by the operator then all is fine.</p>
<p>We take advantage of the new integration testing functionality to make some extensive changes to logging and exception handling of the controller code. By running the integration tests we make sure all seems to work fine  (even though we still need some proper unit testing of the controller). Modifications are made quite quickly thanks to the integration tests.</p>
<p>To recap, we&#8217;ve added integration testing support to the existing &#8216;test.extender&#8217; bundle and created integration testing code for the cache controller component. This has allowed us to make code changes quickly with less risk of mistakes.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-06/test-extender-patch.txt">Here</a> you can find a patch for the test extender project as well as the patched <a href="http://dani.calidos.com/img/2010/osgi-06/test.extender-1.0-SNAPSHOT.jar">testing bundle</a> already compiled. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Components on the server (5): better Unit Testing</title>
		<link>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/</link>
		<comments>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 23:20:15 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[java servlets]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=217</guid>
		<description><![CDATA[In this installment of the OSGi series, we add more complete Unit Testing support in the project. We also establish that some behaviour of the Servlet Bridge may not be what we want  and then provide a way to customize it.

Please make sure you read the previous installments before you continue with this article…
To [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the OSGi series, we add more complete Unit Testing support in the project. We also establish that some behaviour of the Servlet Bridge may not be what we want  and then provide a way to customize it.</p>
<p><span id="more-217"></span></p>
<p>Please make sure you read the<a href="http://dani.calidos.com/category/computing/java/"> previous installments </a>before you continue with this article…</p>
<p>To ensure greater flexibility, performance and encapsulation, we will be using OSGi fragments.</p>
<p>http://static.springsource.org/osgi/docs/1.1.3/reference/html/appendix-tips.html</p>
<p>OSGi fragments attach to &#8220;host&#8221; bundles and can be used to extend functionality, provide configuration and even extra manifest entries.</p>
<p>On the first part, we move our unit tests to fragments. This has the benefit of being able to separate tests from actual code as well as allowing us to deploy using a smaller footprint in situations where we don&#8217;t want test code such as production deployments.</p>
<p>If we start with the cache code we&#8217;ve got so far we need to separate the test code from two bundles: &#8216;com.calidos.dani.osgi.cache.provider.memory&#8217; and &#8216;com.calidos.dani.osgi.cache.provider.memcached&#8217;. That is easy enough.</p>
<p>We create a new OSGi bundle fragment project like this:</p>
<p><img alt="New fragment" src="http://dani.calidos.com/img/2010/osgi-05/new-fragment.png" title="New fragment" width="472" height="566" /></p>
<p>We specify the bundle the new fragment is attaching to:</p>
<p><img alt="Specify host bundle" src="http://dani.calidos.com/img/2010/osgi-05/specify-bundle.png" title="Specify host bundle" width="455" height="107" /></p>
<p>The next step is to move the JUnit code from the main bundle onto the fragment. If we run the test independently we see that it passes as the classpath of the host and fragment bundles is merged into one.</p>
<p>We then add the fragment to our existing run configuration and it will be loaded onto our environment. So far so good, but there is no way to run the tests outside our controlled Eclipse.</p>
<p>Slim Ouertani at Javalobby shows us how to <a href="http://java.dzone.com/articles/osgi-junit-test-extender-using">run fragment tests from within the OSGi environment</a> in a great article. His code uses the new bundle tracker feature to discover any test fragments and exposing functionality to be able to run the tests.</p>
<p>You can get the source at kenai: <a href="http://kenai.com/projects/testosgifragment">http://kenai.com/projects/testosgifragment</a></p>
<p>We read the article thoroughly, fetch the source and build test.extender using maven:</p>
<p><code><br />
mvn install<br />
</code></p>
<p>The code works great but has a bug which is triggered when the code looks for the host of the fragment by reading the &#8216;Fragment-Host:&#8217; header. If the value specifies any kind of version qualifier it fails. It also crashes when trying to test a bundle or a fragment that doesn&#8217;t have the &#8216;Unit-Test&#8217; custom header.</p>
<p>The &#8216;Unit-Test&#8217; custom header lives on the fragment manifest and is used by test.extender to control who is able to be tested and if tests are done manually or automatically.</p>
<p>If no &#8216;Unit-Test&#8217; header is present or if its value is empty, test.extender will refuse to run any tests present on the bundle. If the value is &#8216;true&#8217; then test.extender will run the tests automatically whenever the test fragment bundle is loaded. If the value is anything else the tests won&#8217;t run automatically but you can still run them using the &#8216;test&#8217; and &#8216;testall&#8217; commands.</p>
<p>I have patched the code to accept a version qualifier for the fragment host as well as giving out an informative error message when attempting to test the wrong bundle.</p>
<p>Once this is done, we play with the test.extender by obtaining the fragment bundle id and issuing &#8216;test &lt;id&gt;&#8217; on the console:</p>
<p><code><br />
osgi&gt; test 80<br />
Bundle : [80] : com.calidos.dani.osgi.cache.provider.memory.test<br />
_<br />
CLASS : [com.calidos.dani.osgi.cache.provider.memory.test.MemoryCacheTest]<br />
___________________________________________________________________________<br />
Method : [ testClear ] PASS<br />
Method : [ testInit ] PASS<br />
Method : [ testInitInt ] PASS<br />
Method : [ testSize ] PASS<br />
Method : [ testSet ] PASS<br />
Method : [ testGet ] PASS<br />
Method : [ testGetStatus ] PASS<br />
___________________________________________________________________________<br />
_<br />
</code></p>
<p>We can also use the &#8216;testall&#8217; command which will look for all the testable fragment bundles and run the test there.</p>
<p>Having tested that functionality, we separate the tests from the memcached bundle and move them onto their own bundle.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-05/test-fragments.tar.gz">Here</a> you can download the two test fragments and the <a href="http://dani.calidos.com/img/2010/osgi-05/test-extender-patch">patch</a> to modify test.extender, neat.</p>
<p>Ok then, we move onto the next thing that is looking closely at the Servlet Bridge and its behaviour. What we are interested in is what happens when the container deploys and inits the Web app itself, starting up the servlet bridge. The bridge uses the container temporary folder to deploy the OSGi environment in a subfolder, copying any bundles into that subfolder. If the subfolder exists and there are bundles that have the same names, they won&#8217;t be copied. I have found this behaviour to be very confusing for newbies to the platform and very annoying for veterans. I&#8217;m not entirely sure if this is deliberate and has performance reasons or what. Calling the framework controls to prevent that is not optimal and manually removing the temporary folder isn&#8217;t, either. One possible solution would be to use a building system that increments the micro number every time there is a build and remember to clear up the container temporary folder from time to time. That is not always desirable or possible but fortunately, the servlet bridge implementation provides a way to customize it to our heart&#8217;s content.</p>
<p>Basically we have the following code in the bridge init() method:</p>
<pre class="java:nocontrols:nogutter">
	framework.init(getServletConfig());
	framework.deploy();
	framework.start();
	frameworkStarted = true;
</pre>
<p>In this case, &#8216;framework&#8217; is a instance of the FrameworkLauncher class which is created just before this code snippet. The FrameworkLauncher is the class responsible for deploying and launching OSGi. We note that the object is created by default as a plain FrameworkLauncher instance. However, the class to be used can be customized by specifying it in the web.xml file using the  &#8216;frameworkLauncherClass&#8217; servlet initialization parameter. As long as that class is a subclass of FrameworkLauncher the appropriate contract is fulfilled.</p>
<p>This means we can override some behaviour and delete the framework deployment folders upon startup:</p>
<pre class="java:nocontrols:nogutter">
@Override
public void init() {

super.init();

File servletTemp = (File) context.getAttribute("javax.servlet.context.tempdir");
File platformDirectory = new File(servletTemp, "eclipse");

if (platformDirectory.exists()) {
	deleteDirectory(platformDirectory);
}

}
</pre>
<p>Cool, so we need to export this as a jar file named dani-frameworklauncher.jar into the package project lib folder:</p>
<p><img alt="Export framework launcher" src="http://dani.calidos.com/img/2010/osgi-05/export-launcher.png" title="Export framework launcher" width="485" height="589" /></p>
<p>Next we change the servletbridge web.xml configuration parameter to load the new framework launcher:</p>
<p><code><br />
&lt;init-param&gt;<br />
&lt;param-name&gt;frameworkLauncherClass&lt;/param-name&gt;<br />
&lt;param-value&gt;com.calidos.dani.osgi.servletbridge.FrameworkLauncher2&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
</code></p>
<p>To test, we can add a file onto the $APACHE_TOMCAT/work/Catalina/localhost/<webappname>/eclipse folder and restart Tomcat. Before this new launcher was in place, the file would be kept but now it is deleted alongside the rest. Any other methods can also be extended to customize the bridge behaviour without having to modify the launcher class.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-05/dani-framework-launcher.tar.gz">Here</a> you can download the framework launcher project, put it on the WEB-INF/lib folder alongside the servlet bridge and enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
