ClassCastException while parsing SimpleCov JSON

I want to let Sonarqube to show coverage produced by SimpleCov (Ruby). So I installed SimpleCov and SimpleCov-JSON formatter for this, updated config like described by doc. JSON-Report will be produced (see JSON section). But I get an exception (see below). What is wrong with JSON or my configuration?

Exception

|24-Jan-2019 09:06:55 |INFO: Sensor SimpleCov Sensor for Ruby coverage [ruby]|
|---|---|
|24-Jan-2019 09:06:55 |ERROR: Cannot read coverage report file, expecting standard SimpleCov resultset JSON format: './test-build/coverage.json'|
|24-Jan-2019 09:06:55 |java.lang.ClassCastException: java.lang.String cannot be cast to org.sonarsource.analyzer.commons.internal.json.simple.JSONObject|
|24-Jan-2019 09:06:55 |        at org.sonarsource.ruby.plugin.SimpleCovSensor.mergeFileCoverages(SimpleCovSensor.java:112)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.ruby.plugin.SimpleCovSensor.execute(SimpleCovSensor.java:71)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.sensor.SensorWrapper.analyse(SensorWrapper.java:45)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.phases.SensorsExecutor.execute(SensorsExecutor.java:88)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.phases.SensorsExecutor.execute(SensorsExecutor.java:62)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.phases.AbstractPhaseExecutor.execute(AbstractPhaseExecutor.java:74)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:164)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:319)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:314)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:288)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.task.ScanTask.execute(ScanTask.java:48)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.task.TaskContainer.doAfterStart(TaskContainer.java:82)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)|
|24-Jan-2019 09:06:55 |        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)|
|24-Jan-2019 09:06:55 |        at org.sonar.scanner.bootstrap.GlobalContainer.executeTask(GlobalContainer.java:131)|
|24-Jan-2019 09:06:55 |        at org.sonar.batch.bootstrapper.Batch.doExecuteTask(Batch.java:116)|
|24-Jan-2019 09:06:55 |        at org.sonar.batch.bootstrapper.Batch.executeTask(Batch.java:111)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:63)|
|24-Jan-2019 09:06:55 |        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)|
|24-Jan-2019 09:06:55 |        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)|
|24-Jan-2019 09:06:55 |        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)|
|24-Jan-2019 09:06:55 |        at java.lang.reflect.Method.invoke(Method.java:497)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)|
|24-Jan-2019 09:06:55 |        at com.sun.proxy.$Proxy0.execute(Unknown Source)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:233)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.api.EmbeddedScanner.runAnalysis(EmbeddedScanner.java:151)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.cli.Main.runAnalysis(Main.java:123)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.cli.Main.execute(Main.java:77)|
|24-Jan-2019 09:06:55 |        at org.sonarsource.scanner.cli.Main.main(Main.java:61)|

JSON

{
    "timestamp": 1548317201,
    "command_name": "RSpec",
    "files": [{
        "filename": "path/lib/mytool/command.rb",
        "covered_percent": 43.24324324324324,
        "coverage": [null, null, null, null, null, null, null, null, 1, null, 1, 1, 1, null, 1, null, null, null, null, 1, 0, null, null, null, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null, null, null, null, null, 1, 0, 0, null, null, null],
        "covered_strength": 0.4,
        "covered_lines": 16,
        "lines_of_code": 37
    }, {
        "filename": "path/lib/mytool/commands/changelog.rb",
        "covered_percent": 96.0,
        "coverage": [null, null, null, null, null, null, null, null, 1, 1, 1, 1, 1, 1, 1, null, 1, 1, null, null, 1, 1, 1, 1, 1, 1, 1, 1, null, 1, 2, null, 2, null, null, 2, 2, null, null, 1, 2, 2, 2, 2, null, null, 1, null, null, 1, 2, 2, 2, null, 2, null, 2, 2, 0, 0, null, 2, null, null, null, null, 1, 2, 2, null, null, null, 1, 2, 2, null, null, null, 1, 2, null, 2, 2, null, null, 1, null, 1, null, null, null],
        "covered_strength": 1.4,
        "covered_lines": 48,
        "lines_of_code": 50
    }, {
        "filename": "path/lib/mytool/commands/copyright.rb",
        "covered_percent": 54.83870967741935,
        "coverage": [null, null, null, null, null, null, null, null, 1, 1, 1, 1, 1, 1, null, 1, 1, null, 1, null, null, 1, 0, null, null, null, null, null, 1, 0, null, 0, null, 0, 0, null, null, 1, null, null, null, null, 1, 0, null, null, null, null, 1, 0, 0, null, null, null, null, null, 1, 0, null, 0, 0, null, 0, null, null, null, null, null, null, 1, 0, null, null, null, null, null, null, 1, 0, null, null, null, null],
        "covered_strength": 0.5,
        "covered_lines": 17,
        "lines_of_code": 31
    }, {
        "filename": "path/lib/mytool/commands/release.rb",
        "covered_percent": 63.1578947368421,
        "coverage": [null, null, null, null, null, null, null, null, 1, 1, 1, 1, null, 1, 1, null, 1, 1, null, 1, 0, null, 0, null, null, 1, 0, 0, 0, 0, null, 0, null, null, 1, null, 1, null, null, null],
        "covered_strength": 0.6,
        "covered_lines": 12,
        "lines_of_code": 19
    }, 
...
    {
        "filename": "path/lib/mytool/common/ui.rb",
        "covered_percent": 100.0,
        "coverage": [null, null, null, null, null, null, null, null, 1, null, 1, 1, 1, 9, null, null, 1, 1, 1, 1, null, null, 1, 3, null, null, 1, 1, null, null, 1, 1, null, null, 1, 1, null, null, 1, 1, null, null, 1, 1, null, null, 1, null, 1, null, null],
        "covered_strength": 1.4,
        "covered_lines": 23,
        "lines_of_code": 23
    }],
    "metrics": {
        "covered_percent": 72.79549718574108,
        "covered_strength": 321.0551594746717,
        "covered_lines": 388,
        "total_lines": 533
    }
}

sonar-project.properties

sonar.projectKey="KEY"
sonar.projectName="Mytool"
sonar.projectVersion="v0.1.0"
sonar.sourceEncoding=UTF-8
sonar.sources=lib
sonar.exclusions=**/node_modules/**,**/*_spec.rb
sonar.tests=spec
sonar.test.inclusions=**/*_spec.rb
sonar.ruby.coverage.reportPaths=./test-build/coverage.json
sonar.ruby.rubocop.reportPaths=./test-build/rubocop-report.json

Environment

  • SonarQube v. 7.4 (build 18908)
  • SonarRuby Plugin v. 1.4.0 (build 155)
  • Scanner v. 3.0.3.778
  • Ruby v. 2.5.0
  • SimpleCov v. 0.16.1
  • SimpleCov-Json v. 0.2

Hello @Tharnilich,

Thank you for the detailed information, it makes it much easier to help you :slight_smile:
Your problem is that the SimpleCov coverage report to be imported is not the one generated by the SimpleCov-JSON formatter.
SimpleCov itself, by default, also creates a JSON report file on top of the html report.
This report to be imported is the file coverage/.resultset.json, which has a different format compared to the SimpleCov-JSON report.
Importing this file instead should fix your issue.

Best,
-Chris

1 Like

Hello @czurn,
Thank you, it works!