Kotlin - Code Coverage Remains At Zero Although There Are Unit Tests

  • Version where the coverage doesn’t work: * Developer Edition 8.9.7 (build 52159)
  • Version where the coverage works as intended: Community Edition - Version 10.0(build 68432)
  • Code analysis is triggered via Azure Pipelines
  • I’m trying to see the code coverage for my Kotlin project. We were able to show it in our local machine. However not on the web version. I would like to be able to view it on the web version as well. I can provide additional data if requested.

Web Version (Developer Edition):

Local Version (Community Edition):

The settings in the yaml is as following;

  - task: SonarQubePrepare@5
    inputs:
      SonarQube: 'SonarQubeDev'
      scannerMode: 'Other'
      extraProperties: |
        sonar.projectName=name_Android
        sonar.projectKey=name_Android
        sonar.modules=app
        sonar.exclusions=debug/src,pinview/**,textinputlayout/**,src/debug/,src/main/assets/,src/main/res/,**/*.png,**/*.png,**/R.class,**/BuildConfig.*,**/Manifest*.*,**/com/example/databinding/*,**/com/example/generated/callback/*,**/*Dto*.*,**/android/databinding/*,**/androidx/databinding/*,**/di/module/*,**/*MapperImpl*.*,**/BuildConfig.*,**/*Component*.*,**/*BR*.*,**/Manifest*.*,**/*Companion*.*,**/*Module.*,**/*Dagger*.*,**/*MembersInjector*.*,**/*Extensions*.*,**/InputMethodManagerLeaks.*,**/*_Factory*.*,**/*_Provide*Factory*.*,**/*Constants*.*,**/binding/*,**/di/*,**/core/*,**/util/*,**/debug/*
        sonar.test.inclusions=**/*Test*.kt
        sonar.tests=src/test,src/androidTest
        sonar.host.url=https://sonarqubedev.company.com
        sonar.login=loginInfo
        sonar.coverage.exclusions=**/R.class,**/BuildConfig.*,**/Manifest*.*,**/com/example/databinding/*,**/com/example/generated/callback/*,**/*Dto*.*,**/android/databinding/*,**/androidx/databinding/*,**/di/module/*,**/*MapperImpl*.*,**/BuildConfig.*,**/*Component*.*,**/*BR*.*,**/Manifest*.*,**/*Companion*.*,**/*Module.*,**/*Dagger*.*,**/*MembersInjector*.*,**/*Extensions*.*,**/InputMethodManagerLeaks.*,**/*_Factory*.*,**/*_Provide*Factory*.*,**/*Constants*.*,**/binding/*,**/di/*,**/core/*,**/util/*,**/debug/*
        sonar.coverage.jacoco.xmlReportPaths=$(Pipeline.Workspace)/reports/app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
      enabled: true

When I view the tasks on azure, I see that SonarQubeAnalyze task takes <1 seconds.

The order of yaml tasks is as following

  • task: SonarQubePrepare@5
  • task: Gradle@2
  • task: Gradle@2
  • task: AndroidSigning@3 (displayName: 'Signing and aligning APK file(s) /*.apk’)
  • task: CopyFiles@2 (displayName: ‘Copy Files to artifacts’)One of these files include the coverage report.
  • task: CopyFiles@2 (displayName: ‘Copy code coverage report to artifacts’)
  • task: PublishTestResults@2
  • task: PublishCodeCoverageResults@1
  • task: SonarQubeAnalyze@5
  • task: SonarQubePublish@5

Finally the raw yaml code is as following:

steps:
  - script: echo I am building!
    displayName: 'Run Build'

  - task: SonarQubePrepare@5
    inputs:
      SonarQube: 'SonarQubeDev'
      scannerMode: 'Other'
      extraProperties: |
        sonar.projectName=name_Android
        sonar.projectKey=name_Android
        sonar.modules=app
        sonar.exclusions=debug/src,pinview/**,textinputlayout/**,src/debug/,src/main/assets/,src/main/res/,**/*.png,**/*.png,**/R.class,**/BuildConfig.*,**/Manifest*.*,**/com/example/databinding/*,**/com/example/generated/callback/*,**/*Dto*.*,**/android/databinding/*,**/androidx/databinding/*,**/di/module/*,**/*MapperImpl*.*,**/BuildConfig.*,**/*Component*.*,**/*BR*.*,**/Manifest*.*,**/*Companion*.*,**/*Module.*,**/*Dagger*.*,**/*MembersInjector*.*,**/*Extensions*.*,**/InputMethodManagerLeaks.*,**/*_Factory*.*,**/*_Provide*Factory*.*,**/*Constants*.*,**/binding/*,**/di/*,**/core/*,**/util/*,**/debug/*
        sonar.test.inclusions=**/*Test*.kt
        sonar.tests=src/test,src/androidTest
        sonar.host.url=https://sonarqubedev.company.com
        sonar.login=loginInfo
        sonar.coverage.exclusions=**/R.class,**/BuildConfig.*,**/Manifest*.*,**/com/example/databinding/*,**/com/example/generated/callback/*,**/*Dto*.*,**/android/databinding/*,**/androidx/databinding/*,**/di/module/*,**/*MapperImpl*.*,**/BuildConfig.*,**/*Component*.*,**/*BR*.*,**/Manifest*.*,**/*Companion*.*,**/*Module.*,**/*Dagger*.*,**/*MembersInjector*.*,**/*Extensions*.*,**/InputMethodManagerLeaks.*,**/*_Factory*.*,**/*_Provide*Factory*.*,**/*Constants*.*,**/binding/*,**/di/*,**/core/*,**/util/*,**/debug/*
        sonar.coverage.jacoco.xmlReportPaths=$(Pipeline.Workspace)/reports/app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
      enabled: true

  - task: Gradle@2
    inputs:
      gradleWrapperFile: 'gradlew'
      options: '-PversionName=$(prodVersionName) -PversionCode=$(prodVersionCode) -PdemoName=$(demoName) -PdemoP=$(demoP) -PstaticName=$(staticName) -PstaticP=$(staticP) -PsecretKey=$(secretKey) -PbaseUrl=$(prodBaseURL) -uatBaseUrl=$(uatBaseURL) -PsdkBaseUrl=$(SDKBaseURL) -UatBaseUrl=$(SDKUatBaseURL)'
      tasks: 'clean assembleDebug'
      publishJUnitResults: false
      javaHomeOption: 'JDKVersion'
      gradleOptions: '-Xmx3072m'
      sonarQubeRunAnalysis: true
      sqGradlePluginVersionChoice: 'specify'
      sonarQubeGradlePluginVersion: '3.3'
      spotBugsAnalysis: false

  - task: Gradle@2
    inputs:
      workingDirectory: ''
      options: '-PversionName=$(ProdVersionName) -PversionCode=$(prodVersionCode) -PdemoName=$(demoName) -PdemoP=$(DemoP) -PstaticName=$(staticName) -PstaticP=$(staticP) -PsecretKey=$(secretKey) -PbaseUrl=$(baseURL) -UatBaseUrl=$(UatBaseURL) -BaseUrl=$(BaseURL) -UatBaseUrl=$(UatBaseURL)'
      gradleWrapperFile: 'gradlew'
      gradleOptions: '-Xmx3072m'
      publishJUnitResults: true
      testResultsFiles: '**/TEST-*.xml'
      javaHomeOption: 'JDKVersion'
      sonarQubeRunAnalysis: true
      sqGradlePluginVersionChoice: 'specify'
      sonarQubeGradlePluginVersion: '3.3'
      tasks: 'clean test build jacocoTestReport -x connectedCheck -x connectedDebugAndroidTest -x createDebugAndroidTestCoverageReport'



  - task: AndroidSigning@3
    displayName: 'Signing and aligning APK file(s) **/*.apk'
    inputs:
      apkFiles: '**/*.apk'
      apksignerKeystoreFile: 'keystore.jks'
      apksignerKeystorePassword: '$(keystore-password)'
      apksignerKeystoreAlias: '$(key-alias)'
      apksignerKeyPassword: '$(key-password)'
      apksignerArguments: '--out $(Build.SourcesDirectory)/app/build/outputs/apk/debug/dev.release.apk'
      zipalign: false

  - task: CopyFiles@2
    displayName: 'Copy Files to artifacts'
    inputs:
      SourceFolder: '$(Build.SourcesDirectory)'
      Contents: '**/*.release.apk'
      TargetFolder: '$(build.artifactStagingDirectory)'
      OverWrite: true
    condition: succeededOrFailed()

  - task: CopyFiles@2
    displayName: 'Copy code coverage report to artifacts'
    inputs:
      SourceFolder: '$(Build.SourcesDirectory)'
      Contents: '**/jacocoTestReport.xml'
      TargetFolder: '$(build.artifactStagingDirectory)'
      OverWrite: true
    condition: succeededOrFailed()

  # Publish the folder as pipeline artifact
  - publish: $(Build.ArtifactStagingDirectory)
    artifact: artifacts

  - task: PublishTestResults@2
    inputs:
      testResultsFormat: 'JUnit'
      testResultsFiles: '$(Build.SourcesDirectory)/app/build/reports/tests/testDebugUnitTest'
      searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
      mergeTestResults: true
      failTaskOnFailedTests: false
      ##testRunTitle: # Optional
      #buildPlatform: # Optional
      #buildConfiguration: # Optional
      publishRunAttachments: true

  - task: PublishCodeCoverageResults@1
    inputs:
      codeCoverageTool: 'JaCoCo'
      summaryFileLocation: '$(Build.SourcesDirectory)/app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml'
      reportDirectory: '$(Build.SourcesDirectory)/app/build/reports/jacoco/jacocoTestReport/html'

  - script: echo sonar publish I am publishing to SonarQube!
    displayName: 'Run Sonar Publish'
  - download: current
    artifact: artifacts
    patterns: '**/jacocoTestReport.xml'

  - task: SonarQubeAnalyze@5

  - task: SonarQubePublish@5
    inputs:
      pollingTimeoutSec: '300'

What do the logs say about importing code coverage?

Hi Colin, thank you for the reply, you may find the logs below:

Output.txt (532.6 KB)

Hi Colin,

Thank you for help/response.

We are using this SonarQubePrepare step. But we have gotten following error. We didn’t find any solution about this.

  • task: SonarQubePrepare@5
    inputs:
    SonarQube: ‘SonarQubeDev’
    scannerMode: ‘CLI’
    configMode: ‘manual’
    cliProjectKey: ‘AppKEY’
    extraProperties: |
    sonar.host.url=“CompanyURL”
    sonar.login=LoginKEY
    sonar.projectName=AppName
    sonar.projectKey= AppName
    sonar.tests=app/src/test
    sonar.exclusions=/pinview/,/textinputlayout/,/src/debug/*,/src/main/res/,**/.png,/*.png,/R.class,/BuildConfig.*,/com/example/databinding/,**/com/example/generated/callback/,/Dto.*,/android/databinding/,**/androidx/databinding/,/di/module/*,/MapperImpl.,**/Component.,/BR.*,/Manifest*.,.,/Companion.*,/Module.,/Dagger.*,/MembersInjector.,**/Extensions.,/InputMethodManagerLeaks.*,/_Factory.,**/_ProvideFactory.,**/Constants.,/binding/*,/di/,**/core/
    sonar.coverage.exclusions=/R.class,/BuildConfig.,**/com/example/databinding/,/com/example/generated/callback/*,/Dto.,**/android/databinding/,/androidx/databinding/*,/di/module/,**/MapperImpl.,/Component.*,/BR.,**/Manifest.,**/Companion.,/Module.,/Dagger.,**/MembersInjector.,/Extensions.*,/InputMethodManagerLeaks.,**/_Factory*.,**/_ProvideFactory.,**/Constants.,/binding/*,/di/,**/core/,/src/main/java/util/*,/debug/*
    sonar.coverage.jacoco.xmlReportPaths=$(Pipeline.Workspace)/artifacts/app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
    enabled: true

Best Regard.

These really seem like two different problems. Are you both working together on the same project?

If you’re analyzing a Java project built by gradle, you should use the SonarScanner for Gradle (gradle sonarqube and not the Scanner CLI.

And, I just saw this:

SonarQube v8.9.7 is an EOL version of SonarQube. If it works on a newer (supported) version of v9.9 LTS and v10.0 – well, there’s your answer. Upgrade to a supported version!

Thank you Colin,
We have notified the department with our update request. I will update you when we try it.