Unit testing Eclipse RCP applications

There are different notions of what an unit test actually is. While most will agree that it is a test that verifies a pretty small part of a software system, we don’t all agree on how big a part this is. Personally I want a unit test to cover as little as possible. This, I think, makes the tests more manageable and makes it more likely that we can execute them with a minimum of fuss and in the shortest time possible. The following sums it up:

A unit test is an automated piece of code that invokes the smallest testable part of a system and then checks a single assumption about the behavior of that part.

Because a these tests verifies such a small part of the system I think a unit test should be in the same bundle as the code it is testing. And since it is only testing code contained withing the same bundle, it won’t need any extra dependencies (except for Junit). Setting this up when using the traditional PDE Build cannot be easily done without including test code in deployed bundles. As a workaround you can create a plug-in fragment to host unit tests. That will work, but causes other complications. Apart from the hassle of managing an extra bundle, you will for example not be able to verify platform specific code hosted in a fragment using tests hosted in another fragment. You’ll want these tests to be in the platform specific fragment.

Hosting the tests in the same bundle as the tested code is not very straightforward when using Tycho and Maven either, but it is possible and well worth the effort. I’d like to propose a solution.

The first thing we’ll do is to set up the project in the Eclipse IDE. As you may know, Maven by default expects a root src folder with main and test subfolders. This layout is not commonly found in Eclipse bundles, nor is it default when creating new plug-ins. Also we don’t want the eclipse-plugin packaged bundles to include the tests. So that’s why I elected to add another src-test folder instead. Do as follows:

  1. Add a new source folder for tests, src-test
  2. Exclude this in build.properties by adding src.excludes = src-test/
  3. Add Junit libraries to the build path. Go to Project properties > Java Build Path > Libraries. Add “Junit 4”.

Unit tests

Unit tests now go in the src-test folder of the bundle. And because the dependecy to Junit 4 is added to project properties and not the MANIFEST.MF, we can compile and run the test code without the org.junit bundle ending up in the product. To hone you TDD skills you may now consider installing a tool for continusly running your unit tests. Infinitest is a good candidate.

Infinitest

Tycho will not automatically pick up these tests so we need to add some configuration in the pom.xml to let Maven know that we have these:

  1. The test source folder must be specified (src-test).
  2. The Maven compiler plug-in must be bound to the test-compile phase so the tests gets compiled.
  3. The Maven Surefire plug-in must be activated

  ${project.basedir}/src-test
  
    ...
    
      org.apache.maven.plugins
      maven-surefire-plugin
      2.12.4
      
        
          test
          test
          
            
              **/*Test.java
            
          
          
            test
          
        
      
    
    
      org.apache.maven.plugins
      maven-compiler-plugin
      2.5.1
      
        
          compiletests
          test-compile
          
            testCompile
          
        
      
    
  

And that’s all there’s to it. Now, integration tests and UI tests should go into separate bundles packaged as eclipse-test-plugin as before. These will be executed in the Maven integration-test phase. Well after the test phase in which these tests will execute. So if there are any issues uncovered by the unit tests, the build will fail as soon as possible.

References: