Code coverage is not showing on Sonarqube for Typescript

Viewed 8298

I am using Sonarqube analysis for my Nestjs project. While I run the unit tests with jest, they are all passing and code coverage was about 80%. On Sonarqube it is still showing as 0%.

My sonar-project.properties file is as follows

sonar.projectKey=<project-key>
sonar.projectName=
sonar.sources=src
sonar.tests=src
sonar.inclusions=**
sonar.test.inclusions=src/**/*.spec.ts
sonar.testExecutionReportPaths=test-report.xml
sonar.exclusions=node_modules 

My jest.json is as follows

{
"moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "json"
  ],
  "transform": {
      "^.+\\.tsx?$": "ts-jest"
  },
  "testRegex": "/src/.*\\.(test|spec).(ts|tsx|js)$",
  "collectCoverageFrom" : ["src/**/*.{js,jsx,tsx,ts}", "!**/node_modules/**", "!**/vendor/**"],
  "coverageReporters": ["json", "lcov"]
}

The relevant parts of my package.json

  "devDependencies": {
"@nestjs/cli": "^7.5.4",
"@nestjs/schematics": "^7.2.7",
"@nestjs/testing": "^7.6.11",
"@types/jest": "^26.0.20",
"@types/node": "^14.14.25",
"@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.14.2",
"@typescript-eslint/parser": "^4.14.2",
"eslint": "^7.19.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^26.6.3",
"jest-sonar-reporter": "^2.0.0",
"prettier": "^2.2.1",
"serverless": "^2.23.0",
"supertest": "^6.1.3",
"ts-jest": "^26.5.0",
"ts-loader": "^8.0.15",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.1.3"
  },
  "jest": {
"testResultsProcessor": "jest-sonar-reporter",
"moduleFileExtensions": [
  "js",
  "json",
  "ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
  "^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
  "**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}

My source code and their respective unit tests are in the same location. The test files have the extension .spec.ts

While running tests locally, all tests are passing and test-report.xml is generated on the local repo. We are also running unit tests on Jenkins as a stage just before running sonar scanner.

Sonarqube code coverage is important metric for us and without which the pipeline does not move further. Any tips here?

Sonarqube Enterprise Edition Version 7.9.5 (build 38598)

2 Answers

Have you tried specifying the path to your lcov.info file like so: sonar.javascript.lcov.reportPaths=coverage/lcov.info

These parameters are documented here:

I can't be certain, but your symptoms match what I saw when I discovered a bug in the SonarTS plugin. We're using a somewhat old version of SonarQube (7.9.2). You haven't said what version you're using.

What I discovered from somewhat random experimentation is that if a file path in the "lcov.info" file crosses a symbolic link, the SonarTS plugin will not be able to open the file, thus finding zero coverage for that file. If a single file in the lcov.info file crosses a symbolic link, it's likely that all of them will.

I fixed this by writing a script that processes the lcov.info file, replacing all file paths with their "absolute" file paths, following symbolic links.

The code in our Jenkins shared library looks something like this:

shterse "cat coverage/lcov.info | " +
   "while IFS= read -r line; do if [[ \"\$line\" == \"SF:\"* ]]; then line=\"SF:\$(realpath \"\${line#SF:}\")\"; fi; echo \"\$line\"; done > /tmp/lcov.info"
sh "mv /tmp/lcov.info coverage/lcov.info"

Where "shterse" is this:

// This will turn off verbose output.
def shterse(cmd) {
    sh('#!/bin/sh -e\n' + cmd)
}
Related