Tuesday, July 24, 2012

Android Unit Tests and Coverage in Sonar

Some weeks ago I wanted to use Sonar in a small Android-app project to monitor code quality. Using sonar-runner I had very fast a working integration into my development environment and the first measurements were visible.

Most of the measurements like lines of code, violations, complexity or comments were instantly available. But two measures, code coverage and Unit tests, were a bit tricky to integrate. Therefore I will here list the steps I took to enable these two measures in Sonar for Android-app projects.

Prerequisites

  • Running Android development environment (Eclipse + ADT)
  • Running Sonar installation
  • Project already in Sonar
  • For this guide the project is not a maven project
  • Separate Unit Test-project for Android-app with tests

Problems

How do I…

  1. include Unit test results in Sonar?
  2. include Emma coverage reports from Android SDK tools?

Solution to Unit-tests

  1. Let the Unit tests execute in Eclipse.
  2. Export the test run results into a directory of the project, e.g. project-dir/reports.
  3. Use TEST-something.xml as file name. This file can than be read and imported into Sonar.
  4. To get Sonar to read this file we have to configure the Surefire-plugin. To do so open the configuration of our project and select Settings > Surefire. Surefire is a standart plugin.
  5. Enter the directory name into the text field. Depending on your sonar-runner configuration the path may have to include also parent directories, but in general the directory name we created earlier is enough. So enter reports.
  6. Now after running sonar-runner the results of the Unit-tests are included in Sonar!

After new test runs you have to export the file again and after running sonar-runner the new results are included into Sonar. Unfortunately I have not yet found a way to automate the test result export.

Solution to Emma support

To add the coverage results it is much more complicated then for the Unit tests. We have to prepare the following tasks:

  1. Execute our Unit-tests with coverage instrumentation.
  2. Prevent the Execution script to delete the binary result files of Emma.
  3. Get Sonar to accept our result files.

Enable coverage instrumentation

Lucky us, the Android SDK ships with built-in Emma 2.0 support. Following this guide we have to create a config file for ant and just use it.

  1. create the ant script for building the test project. Open command prompt and go to your test project directory:
    android update test-project -m your_main_project_full_path -p 
  2. run
    ant coverage

To ease execution I have created an external tools configuration in Eclipse to run ant. I use the following options in my configuration:

  • Main > Buildfile > ${workspace_loc:/test project-dir/build.xml}
  • Targets > Target execution order > emma, debug, install, test
  • Environment > ANT_HOME = path_to_your_ant_installation (this may not be needed)

Prevent deletion of results

Unfortunately the binary result files are deleted after a html coverage report is created (see test-project-dir/bin/coverage.html). To save the needed files (coverage.ec in test-project-dir/bin and coverage.em in main-project-dir/bin) we have to modify the ant task that runs the coverage test.

  1. open android-sdk-dir/tools/ant/build.xml
  2. search for “Cleaning up temporary files” (around line 1267)
  3. delete the two lines:
    <delete file="${out.absolute.dir}/coverage.ec" />
    <delete file="${out.absolute.dir}/coverage.em" /> 
    

    (this has to be repeated every time the android sdk is updated :( )

Now the two files are not deleted any more and we can copy them after the coverage run in one location and configure Sonar to look for them.

Include in Sonar

To let Sonar know where to find our result files go to the Sonar project configuration, Settings > Emma and enter the path to the result files. The path is relative to the main project.

Unfortunately the current version of the Sonar emma plugin, 1.2.1, only supports emma-2.1 reports. The Android SDK ships with emma 2.0 and as it uses a modified version to run in the Android simulator it is not easily upgraded. On the other side Sonars emma plugin 1.1 supports emma reports of version 2.0, but doesn’t accept file reports provided by sonar-runner. It only supports reports via maven. The sonar-runner-way of including reports is only supported in later versions only supporting emma 2.1.

The solution to this problem was a short look into the Sonar emma plugin jar-file. Here you can easily see that the decoding of the report is done by code from the original emma-2.1.jar file. As the interface of emma didn’t change between version 2.0 and 2.1, the file of emma 2.1 was replaced by emma 2.0 and a new sonar emma plugin version 1.2.1 with the emma 2.0 jar-file was created. You can download it here: Sonar-emma-plugin-1.2.1 with EMMA 2.0.

Now to have Sonar support emma 2.0 reports you just have to replace the original Sonar-emma-plugin with this one and restart Sonar. After the next sonar-runner run you should see the results.
Here is A picture of my current project:

unitcoverage.png

FINISHED! Now we have Sonar utilizing Unit-tests and code coverage from an Android project.