12
votes

I'm trying to integrate the sonar analysis into by TeamCity build process. I have a NUnit build step which runs my unit tests and then runs dotCover for the coverage.

My next step is the sonar-runner. The configuration that currently exists is; gallio.mode=dotCover, sonar.gallio.mode=reuseReport but I also need sonar.gallio.reports.path.

Does anybody know the path to the dotCover report generated in the the previous step?

7

7 Answers

4
votes

I couldn't find a way to do this using the built in NUnit runner. I managed to get it working by using a powershell build step to manually call the required commands.

First step is to run the NUnit tests via Gallio within a dotCover cover call:

& dotCover cover `
/TargetExecutable="C:\Program Files\Gallio\bin\Gallio.Echo.exe" `
/TargetArguments="/report-type:XML /report-name-format:test-report /runner:IsolatedProcess /report-directory:.\Gallio .\Path\Test.dll" `
/Filters="+:WhatToCover" `
/Output=coverage.snapshot

The Gallio test report is then available to be picked up by Sonar with reuseReport, TeamCity automatically detects the test results.

You can make TeamCity directly process the coverage snapshot by writing a service message to standard output:

Write-Host "##teamcity[importData type='dotNetCoverage' tool='dotcover' path='coverage.snapshot']"

To get the coverage info into a format usable by Sonar you need to use the dotCover report command and the undocumented report type TeamCityXML:

& dotCover report /Source=coverage.snapshot /Output=coverage-report.xml /ReportType=TeamCityXML
5
votes

Spent some amount of time on the same issue, but with newer Sonar c# plugin (v.2.3) - Gallio support has been dropped, but the report is still required.

To answer the question directly, TeamCity puts dotcover snapshot file into a temp folder with a name like coverage_dotcover27574681205420364801.data (where digits are random). So

The procedure is:

  1. Create a PowerShell Build step in Team City after the step with test and coverage
    • you may use Command line if you prefer
  2. Get the full dotCover snapshot name in temp folder
  3. Run dotCover to produce a HTML report from a snapshot
    • Note - Sonar (c# plugin v 2.3) supports only dotCover HTML reports
  4. Pass the produced HTML report to sonar

PowerShell script:

$snapshot = Get-ChildItem "%system.teamcity.build.tempDir%" `
     -Filter coverage_dotcover*.data `
     | select -ExpandProperty FullName -First 1

%teamcity.dotCover.home%\dotCover.exe report `
    /ReportType=HTML /Source="$snapshot" `
    /Output="%sonar.coverageReport%"

Now you can specify your report in sonnar runner as sonar.cs.dotcover.reportsPaths='%sonar.coverageReport%'

Where %sonar.coverageReport% is a defined property in a TeamCity

2
votes

It seems TeamCity 2017 no longer creates coverage_dotcover*.data files. Instead it creates *.dcvr files.

There are potentially multiple files which need to be merged before you can create the report. As a result the powershell need updating.

So using the steps provided by Oleksandr, just update the script to be:

$snapshotfiles = Get-ChildItem "%system.teamcity.build.tempDir%" `
 -recurse -Filter *.dcvr `
 | select -ExpandProperty Name

$snapshots = $snapshotfiles -join ";"

%teamcity.dotCover.home%\dotCover.exe merge /Source=$snapshots 
/Output=dotcovermerge.dcvr

%teamcity.dotCover.home%\dotCover.exe report `
/ReportType=HTML /Source=dotcovermerge.dcvr `
/Output="%sonar.coverageReport%"

Then the property %sonar.coverageReport% can be passed to the sonarqube scanner. Btw, you need to create a parameter in TC for %sonar.coverageReport% e.g. "sonarcoverage.html"

2
votes

We are using SonarScanner for MSBuild and needed to add the team city temporary build path to the begin step.

  1. Run the SonarScanner.MSBuild.exe begin command, specifying the temp build directory to be where the reports will be available using
   /d:sonar.cs.dotcover.reportsPaths="%system.teamcity.build.tempDir%".
  1. Build your project using MSBuild

  2. Run your test tool, instructing it to produce a report at the same location specified earlier to the MSBuild SonarQube Runner

  3. Run the SonarScanner.MSBuild.exe end command

1
votes

The coverage report from the nunit/dotcover build step is stored in the teamcity hidden artifacts directory. You need to add that as an artifact dependency in the sonar step. I wouldn't recommend the hidden artifact route but it can be done.

This is the artifact path I used to publish the report which worked for a few weeks then began to fail:

%env.TEAMCITY_DATA_PATH%/system\artifacts\**\%teamcity.build.id%\.teamcity\.NETCoverage\dotCover.snapshot

Once you have the report, your're home free though.

1
votes

Although it might be a bit cumbersome solution, I'm using two chained builds.

The first build configuration builds the solution and runs the tests/coverage, plus saves the dotCover snapshot as an artifact.

The other build has an artifact dependency on the first one on .teamcity/.NETCoverage/dotCover.snapshot and runs "C:\Program Files (x86)\JetBrains\dotCover\v2.7\bin\dotCover.exe" report /ReportType=HTML /Source="dotCover.snapshot" /Output="dotCover.html" and, as the latest step, executes SonarRunner (your project properties file will point to the "dotCover.html").

(Tried with SonarQube 5, dotCover 2.7, TC8)

0
votes

Below is what worked for me. I am on TC 2018.2.4 and the bundled version of the dotCover was not generating anything so I upgraded that to the latest version as well which is 2019.1.1

I could not make the agent use the latest version of the dotcover tools so I had to construct the folder path for that rather than using the default %teamcity.dotCover.home% variable.

I also did not want to use the temp folder as things were getting deleted there by the build.

$snapshot_file_list = Get-ChildItem "%system.teamcity.build.tempDir%" -recurse -Filter coverage_dotcover*.data | select -ExpandProperty FullName
Echo "dotCover Snapshot files"
Echo $snapshot_file_list
$joined_snapshot_files = $snapshot_file_list -join ";"
Echo "Merging data files to %system.teamcity.build.checkoutDir%\dotcovermerge.dcvr"
& "%teamcity.agent.tools.dir%\JetBrains.dotCover.CommandLineTools.2019.1.1\dotCover.exe" merge /Source=$joined_snapshot_files /Output="%system.teamcity.build.checkoutDir%\dotcovermerge.dcvr" /LogFile="%system.teamcity.build.checkoutDir%\dotCover.log"
Echo "Generating dotCover Html report"
Echo "%system.teamcity.build.checkoutDir%\%sonar.coverageReport%"
& "%teamcity.agent.tools.dir%\JetBrains.dotCover.CommandLineTools.2019.1.1\dotCover.exe" report /ReportType=HTML /Source="%system.teamcity.build.checkoutDir%\dotcovermerge.dcvr" /Output="%system.teamcity.build.checkoutDir%\%sonar.coverageReport%"