Bundle: junit
Version 3.8.1.kf4-001

JUnit on OSGI

Bundles to support JUnit testing on a running framework.

There are three bundles involved:

junit
bundle exporting the junit.framework.* classes as well as allowing remote connection to test suites in a running framework via http. This bundle also exports a JUnitService to allow other bundles in the framework access to bundles.
junit_runner
a bundle which automatically finds and runs bundles in a framework. This bundle does not require any http connection, just the junit bundle. See junit_runner/readme.txt for more info.
examples
some small test cases using junit

Requirements:

The junit bundle does not require any other bundles (as of revision 737) but can use the HTTP server and the KF console to make test access easier.

Background

JUnit allows developers to write unit tests by writing classes implementing junit.framework.Test, e.g TestCase, TestSuite etc.

A typical test looks like

 class MyTest extends junit.framework.TestCase {
   public void runTest() {
     ... do some work
     assertTrue(someflag)
   }
 }
As long as these test do not depend on a running framework, they are easy to run using normal tools, but when they depend on the framework, the standard test running tools become insufficient.

Thus, the junit bundle allows remote access to test cases running on a framework, from any normal test tool running on a developer machine.

How it works

  1. Bundle developers write tests for a bundle B just as any other JUnit tests. The tests simply extends TestCase or TestSuite.
  2. The bundle developer register these tests as-is into the OSGi framework, with a service.pid property giving the name of the test. This should normally be the same name as the test. Typically all tests from a bundle is grouped into a TestSuite.

    Example: register a test suite into the framework.

          TestSuite suite = new TestSuite("example1");
    
          suite.addTest(new MyTest());
          Hashtable props = new Hashtable();
          props.put("service.pid", suite.getName());
        
          bc.registerService(Test.class.getName(), suite, props);
    
  3. The junit bundle, when started, registers a servlet in the OSGi web server, if the web server exists. This servlet then allows remote running of the registered test cases. The servlet is available at
          http://:/junit?id=
    
    where == value of the service.pid property exported in 2)

    The only interface that registered tests need to implement is junit.framework.Test

    The junit bundle thus accesses the tests via BundleContext.getService() and needs ServicePermission, if FW security is active.

    Note how *only* step 2) is extra work compared to writing standard JUnit tests.

  4. When actual testing is desired, a single client test class is used on the development machine (which doesn't need to run the framework!)

    The client class name is:

         org.knopflerfish.service.junit.client.JUnitClient
    
    The target host and test id is passed to the client as a system property "suite.url"

    This client test class extends TestSuite and act as a proxy to the actual test, and can thus be passed to any test runner, as

    junit.swingui.TestRunner or junit.textui.TestRunner

    as well as Ant's "junit" task.

    Example: Using the Swing TestRunner

        > java "-Dsuite.url=http://localhost:8080/junit?id=example1" \
           junit.swingui.TestRunner \
           org.knopflerfish.service.junit.client.JUnitClient
    
    This will run the test with id "example1" on localhost:8080

    Note that the class path must be set fo find both junit.jar and the junit_all-1.0.0.jar bundle.

  5. Testing can also be done without using the servlet. The easiest approach is then to use the junit_runner bundle, and provide it with a list of test IDs to run. XML formatted results will then be written to file.
  6. If you are using the KF console, the junit bundle registers a set of commands to list and run test cases.
        > enter junit
        junit> help
        Available junit commands:
         list [-help]  - List available tests
         run [-help] [-out #file#]  - Run a test and dump XML results 
                                          to a file or console.
    
Note1:

The servlet is also capable of exporting the test results as plain HTML. In this case, the client proxy isn't needed. Just point your browser at

   http://:/junit
and you'll get a list of available tests. From this list you can select suites and individual tests to run. The result will be presented as HTML. Note2:
The junit_runner/resource directory contains som XSLT style sheets which may be useful for formatting XML test results to HTML.

Monitoring test case execution

JUnit TestListeners may be used to monitor test case execution.

The junit-bundle will look up all services registered under the class junit.framework.TestListener in the running framework and add them to the TestResult as listeners.

Example: register a test listener into the framework.

      TestListener listener = new MyTestListener();

      bc.registerService(TestListener.class.getName(), listener, null);

JUnit support in bundlebuild.xml

As a convenience, the ant/bundlebuild.xml script contains support for using the JUnit client.

Example: run the swing Test runner from Ant

   > ant -Dtest.id=example1 junit_ext
Example: run Ant's junit task
   > ant -Dtest.id=example1 junit_ant
Tip: Bundles can be installed using the telnet console. The telnet console is installed by the default init.xargs. In this case a bundle can be installed and started by
   > ant install start
The following Ant properties are set as default in bundlebuild.xml:
  http.host              localhost
  http.port              8080
  junit.runner.class     junit.swingui.TestRunner
  junit.formatter        plain
  junit.outfile          junit

Known issues

Bundle Jar docs

junit_all-3.8.1.kf4-001

Exported Packages

PackageVersionProviders
junit.framework3.8.1junit_all-3.8.1.kf4-001
org.knopflerfish.service.junit1.0.0junit_all-3.8.1.kf4-001