2
votes

I'm having difficulties to set up my project in a way so SonarQube reports test coverage per test.

During the analysis with Sonar Scanner I just see

No information about coverage per test.

after reading the JaCoCo execution data.

What are the requirements for this to work? How would a minimal example look that shows coverage per test.

My current environment looks like this:

  • SonarQube 6.4
  • SonarJava 4.12.0
  • Sonar Scanner 3.0.3
  • Eclipse Neon
  • EclEmma 3.0.0/JaCoCo 0.7.9

And my test project looks like this:

Workspace
+- EclipseProject
|  +- bin
|  |  +- foo
|  |  |  +- FooClass.class
|  |  +- tests
|  |     +- FooTestClass.class
|  +- src
|     +- foo
|     |  +- FooClass.java // Class with getter/setter for a private 
|     |                   // instance variable.
|     +- tests
|        +- FooTestClass.java // Two JUnit 4 tests: test1 checks getter,
|                             //                    test2 checks setter.
|
+- xml
|  +- TEST-tests.xml // Export from Eclipse after combined test run, converted to fit Surefire format.
|
+- coverage
|  +- test1.exec // Session export from Eclipse after single test run.
|  +- test2.exec // Session export from Eclipse after single test run.
|
+- sonar-project.properties

As you can see, the execution data is present per test. The content of sonar-project.properties looks like following:

sonar.projectKey=EclipseProject
sonar.projectName=EclipseProject
sonar.projectVersion=1.0.0-20170830
sonar.projectBaseDir=/path/to/Workspace
sonar.sources=src/foo/
sonar.tests=src/tests/
sonar.sourceEncoding=UTF-8
sonar.language=java
sonar.java.source=1.8
sonar.java.binaries=bin/
sonar.java.coveragePlugin=jacoco
sonar.jacoco.reportPaths=/absolute/path/to/coverage/test1.exec,/absolute/path/to/coverage/test2.exec
sonar.junit.reportPaths=/absolute/path/to/xml/
sonar.analysis.mode=publish

I'm not sure what's missing. Maybe files need to be named in a specific way like for test results (only picks up TEST-*.xml reports in the Surefire format)?

1

1 Answers

2
votes

Thanks to the Sonar Java plugin being open source I found the problem:

  private boolean analyzeLinesCoveredByTests(String sessionId,
                      ExecutionDataStore executionDataStore) {

    int i = sessionId.indexOf(' ');
    if (i < 0) {
      return false;
    }
    String testClassName = sessionId.substring(0, i);
    String testName = sessionId.substring(i + 1);
    InputFile testResource = javaResourceLocator
                                .findResourceByClassName(testClassName);
    ...

The ID of the dumped session must be of the form testClassName testName (e.g., in my case that would be tests.FooTestClass test1 for test1). Only then will you see test coverage information in SonarQube.