MS .coverage -> .coveragexml

I’m building a pipeline for an MVC project, it builds fine using vstest and I am able to create a .trx and .coverage. But I cannot seem to find a way to convert the .coverage to an xml file. I’m assuming it needs to be xml or coveragexml based on the SQ argument im using /d:sonar.cs.vscoveragexml.reportsPaths.

I don’t have VS and I’m not really a .NET developer. I have tried using CodeCoverage.exe with this command:
CodeCoverage analyze /output:results.xml "SYSTEM_RSLM-2020-03-11-14_38_06.coverage"
But nothing happens, I get no output from powershell.

So I’m sure that somebody knows how to do from a command line perspective and wondered if they’d be able to share it with me? :slightly_smiling_face:

Hi @jonny7,

The Scanner for MSBuild, as long as you have the proper tools installed on the machine executing it (ie for Coverage, it needs either the Test Tools or an Enterprise Edition of Visual Studio) is taking care of gathering your test results files and convert them to coveragexml if found.
It works like this :

  1. Looking at some TestResults folder in the base directory, for .trx files
    1bis) If not found, fallback to the temp directory of the Azure DevOps agent (if running on such agent for CI)
  2. The .trx file should contain a link to the related .coverage file
  3. If yes, then the CodeCoverage.exe tool is executed, outputing a coveragexml file

Please note that if you provide the d:sonar.cs.vscoveragexml.reportsPaths then no conversion (from coverage to coveragexml) will be tried by the Scanner.

HTH,
Mickaël

Hi @mickaelcaro

Thanks for getting back to me , I do have the CodeCoverage.exe tool installed and in the system path. I get the options when running CodeCoverage help.

I get the unit test count into SonarQube but no coverage.
I can see this in the SQ logs:

INFO: Importing 3 Roslyn reports
INFO: Sensor C# [csharp] (done) | time=1437ms
INFO: Sensor C# Unit Test Results Import [csharp]
INFO: Parsing the Visual Studio Test Results file C:\Jenkins\workspace\nepractice-int\.\drop\DCSVAZDISALM$_DCSV_2020-03-12_08_19_16.trx
INFO: Sensor C# Unit Test Results Import [csharp] (done) | time=344ms
INFO: ------------- Run sensors on project

The trx file does have a link to the .coverage file

If I execute CodeCoverage on my machine though:

CodeCoverage.xml analyze /output:results.coveragexml path/to/.coverage

I can get the coverage file. So it seems ok on my end

This is my command for vstest

vstest.console.exe "C:/Jenkins/workspace/nepractice-int/drop/HealthHome.Tests.dll" /ResultsDirectory:"C:/Jenkins/workspace/nepractice-int/drop" /Logger:trx /Enablecodecoverage'

Can you check that you get results when you open the coverage file in visual studio ? You shall see all your methods and their respectives coverage. (Or, at least, check the size of the file)

I don’t have VS :neutral_face:, but the file is long, I did manually just drop it into my build directory and SonarQube then picked it up. However it said it:

INFO: Parsing the Visual Studio coverage XML report C:\Jenkins\workspace\nepractice-int\.\drop\results.coveragexml
INFO: Adding this code coverage report to the cache for later reuse: C:\Jenkins\workspace\nepractice-int\.\drop\results.coveragexml
INFO: Coverage Report Statistics: 32 files, 0 main files, 0 main files with coverage, 32 test files, 0 project excluded files, 0 other language files.
WARN: The Code Coverage report doesn't contain any coverage data for the included files. For troubleshooting hints, please refer to https://docs.sonarqube.org/x/CoBh

So I’m not sure what’s missing for this to occur, the link listed is also dead

Hi @mickaelcaro

Just want to backtrack a little here. I have the following Jenkins commands:

        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    withCredentials([string(credentialsId: 'sonarqube-key', variable: 'sq_key')]) {
                        sh 'C:/sonar-scanner/SonarScanner.MSBuild.exe begin /key:NAFP-INT /d:sonar.cs.vstest.reportsPaths=**/TestResults/*.trx'
                    }
                }
            }
        }
        stage('Build') {
            steps {
                powershell label: 'building...', script: 'MsBuild.exe /t:Rebuild'
            }
        }
        stage('Test') {
            steps {
                catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
                    powershell label: 'testing...', script: 'vstest.console.exe "C:/Jenkins/workspace/nepractice-int/HealthHome.Tests/bin/Debug/HealthHome.Tests.dll" /Logger:trx /Enablecodecoverage'
                }
            }
        }
        stage('End SonarQube Analysis'){
            steps {
                withSonarQubeEnv('SonarQube') {
                    withCredentials([string(credentialsId: 'sonarqube-key', variable: 'sq_key')]) {
                        sh 'C:/sonar-scanner/SonarScanner.MSBuild.exe end'
                    }
                }
            }
        }

This generates my TestResults folder and inside is the trx, the .trx file has a link to the coverage file:

<UriAttachments>
          <UriAttachment>
            <A href="SALM\SYSTEM_SALM 2020-03-13 11_26_17.coverage"></A>
          </UriAttachment>
        </UriAttachments>

This file never seems to be processed by MSBuild and attempted to be converted to the .xml. I have the testagent installed and on the system path and can manually generate this file. But I’m trying to understand why my SonarScanner.MSBuild doesn’t do this as mentioned earlier?

Hi,

Usually our scanner tries to find the coverage near the trx file in terms of deepness of folders (starting from the trx, we look at the “In” folder beside, then deep dive to find the covergage attached, or if it’s an absolute path we can look there direclty.

If none of these situation are met, then it’s more likely that we don’t do anything with it.

In the logs of the analysis, do you find any message like this :

None of the following coverage attachments could be found

Or

None of the attached coverage reports exist on disk ?

Mickaël

Hi

Inside TestResults, I have the trx file, and a folder with the same name as the .trx file. Inside that folder I have the In folder then inside that another folder with the server name. Inside that folder is the .coverage file. I also have another folder in the same root as the trx file that has the coverage file in it.

- TestResults
   - 2d7faf37-1ce8-400d-8049-be99bca10cd9
         - SYSTEM_SALM 2020-03-13 11_26_17.coverage
   - SALM$_SALM_2020-03-13 11_26_17
        - In
            - SALM
                 - SYSTEM_SALM 2020-03-13 11_26_17.coverage
   - SALM$_SALM 2020-03-13 11_26_17.trx

In terms of logs, no I don’t have any of those messages. Here is a little subset of the output though.

INFO: ------------- Run sensors on module NAFP-INT
INFO: Sensor JaCoCo XML Report Importer [jacoco]
INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=0ms
INFO: Sensor JavaXmlSensor [java]
INFO: Sensor JavaXmlSensor [java] (done) | time=0ms
INFO: Sensor HTML [web]
INFO: Sensor HTML [web] (done) | time=0ms
INFO: Sensor C# [csharp]
WARN: File 'C:\Jenkins\workspace\nepractice-int\HealthHome\App_Start\BundleConfig.cs' referenced by the protobuf 'MetricsInfo' does not exist in the analysis context
........
INFO: Importing 3 Roslyn reports
INFO: Sensor C# [csharp] (done) | time=1359ms
INFO: Sensor C# Unit Test Results Import [csharp]
INFO: Parsing the Visual Studio Test Results file C:\Jenkins\workspace\ne-practice-int\.\TestResults\SALM$_SALM 2020-03-13 11_26_17.trx
INFO: Sensor C# Unit Test Results Import [csharp] (done) | time=313ms
INFO: ------------- Run sensors on project
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=140ms
INFO: SCM Publisher No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.
INFO: CPD Executor 30 files had no CPD blocks
INFO: CPD Executor Calculating CPD for 334 files
INFO: CPD Executor CPD calculation finished (done) | time=610ms
INFO: Analysis report generated in 437ms, dir size=5 MB
INFO: Analysis report compressed in 969ms, zip size=1 MB
INFO: Analysis report uploaded in 187ms
INFO: ANALYSIS SUCCESSFUL, you can browse http://dcsvazdisalm:9000/dashboard?id=NAFP-INT
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://localhost:9000/api/ce/task?id=AXDUSnZ2EwPVgg8OGoHC
INFO: Analysis total time: 29.732 s

Suffering from the same symptoms when running directly from the console. this is my powershell hack/fix. configure sonar with x report pairs -> testresults0.trx & coverage0.coveragexml

    Param([string]$projectDir)

$coverageExe = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe"

function makeFilePathsRelative {
    param([string]$filePath, [string]$find,[string]$replace)

    $tempFilePath = "$env:TEMP\"+([System.GUID]::NewGuid().ToString())
    
    (Get-Content -Path $filePath) -replace [regex]::escape($find), [regex]::escape($replace) | Add-Content -Path $tempFilePath

    Remove-Item -Path $filePath
    Move-Item -Path $tempFilePath -Destination $filePath    
}

function prepareTrx {
Param([string]$projectDir)

    Set-Location $projectDir
    $trxReports = get-childitem -path "." -Recurse -Filter *.trx
    $count = $trxReports.Length; #bug

    $projectDir = (Get-Item -Path ".\").FullName + '\'
    $id = 0
    foreach($trxReport in $trxReports)
    {    
        #makeFilePathsRelative $outFile $projectDir ""
        $outFile = $projectDir+"TestResults"+($id++)+".trx"
        Copy-Item -Recurse -Path $trxReport.FullName -Destination $outfile

        makeFilePathsRelative $outFile '/href=\"([^\"]*)/g' 'href=Coverage"'+ $id +".xml"
    }

    $coverageReports = get-childitem -path "." -Recurse -Filter *.coverage

    $id = 0
    foreach($coverageReport in $coverageReports)
    {    
        #makeFilePathsRelative $outFile $projectDir ""
        $outFile = $projectDir+"Coverage"+($id++)+".coveragexml"

        Write-Host $coverageExe "analyze" "/output:"+$outFile $coverageReport.FullName;

        $params = @(
            "analyze"
            "/output:"+$outFile
            $coverageReport.FullName
        )

        &$coverageExe  $params
    }

}

Thanks for this, I’ll try and do something similar, glad that I’m not the only one experiencing this, shame though, it’s normally such a quick thing to achieve

Hi Mic,
Am using VSTEST and MSBUILD for Sonar Scanner. Am stuck into this issue from past few days and end up with no solution. Could you please suggest me on this.

Am able to get the count of unit test in SonarQube Dashboard. Am getting coveragexml and coverage file also. But it throw a warning by saying that “Skippping filename because it is a test file” . And using below sonar properties.

/d:sonar.cs.vstest.reportsPaths=\\TestResults\\.trx /d:sonar.vbnet.vscoveragexml.reportsPaths=\**\TestResults\.Coveragexml

Any help will be appreciated. Thank You!

Hi,

Could you please use proper code block for the properties so then i can see all the relevant stars ? Otherwise there are considered as markdown / redacted so that’s a bit more difficult.

Thanks.

Hi Mic,

Please find the below attachment:

Hi Mic, I have sent you the properties. Could you please check once

Thanks. Could you please try with forward-slashes (the leading ones are not needed) instead, and change the “Coverage.xml” extension to “coverage.xml” (In case these are case sensitive).

Thanks.