Ensuring “dotnet test” TRX & Coverage files end up in SonarQube

Do feel free to provide any comments/feedback to @TheRichCarey on Twitter

I have written before about using SonarQube to do static analysis, but one issue I never came back to was ensuring that code coverage files generated via a build pipeline end up being picked up by the Sonar Scanner to assess code coverage.

Note that the following I am actually using the ‘dotnet test’ build step, rather than the ‘Vs Test’ one. Do let me know if you find a nice work around for the VS Test variant, as I couldn’t get it to drop coverage files!

The issue

The issue is that:

  • When using VSTest, TRX files are deleted automatically if using version 2+ of the VS Test task as per this stack overflow post.
  • When I switched back to ‘dotnet test’ the same thing appeared to be happening.
  • .coverage files are not output by default
  • TRX and Coverage files are placed in a temporary folder of the build agent rather than the executing agents working directory.
  • Even though SonarQube could detect the tests, it would still register as 0.0% code coverage!

Getting ‘dotnet test’ to collect coverage

The first step was to get the ‘dotnet test’ build step to collect the code coverage, and not just dump TRX files.

To do this, go to the “Arguments” field of the dotnet test build step and append --collect "Code Coverage", as well as ensuring that “Publish test results and code coverage” is enabled.

Ensure generated files are copied to the working directory

As the coverage files will end up in the /tmp folder of the build agent, SonarQube will not be able to scan them.

We will need to add a new build step of “copy files” with the correct filter set to get the .trxand .coverage files from the default temporary directory on the build agent, to the test results folder of the workspace. To do this we need to add the “Copy Files” task into the build and place it after the “VS Test” task. The source folder for the copy will be $(Agent.HomeDirectory)\_work\_temp and the target folder will be $(Common.TestResultsDirectory) – The contents can remain as ** but feel free to filter if required. Example below.

If we run a build now, we should now see files in the TestResults folder of the build agent’s working directory.

I didn’t have to make any changes to the configuration within SonarQube as it should just pick up the coverage files. If I follow the above I get the following (Lets just ignore the fact the number is low πŸ˜‰)

CSPROJ Changes to test projects

One thing I did notice in the console when attempting to fix this code coverage issue was that I got a lot of warnings like:

SonarQube.Integration.targets: warning : The project does not have a valid ProjectGuid. Analysis results for this project will not be uploaded to SonarQube. 

As all my projects were .net core or .net standard the CSPROJ files do not contain a <ProjectGuid> tag by default. As also suggested in this stack overflow answer , I added a GUID to my test project file. I am not 100% if this is required, but it stopped warnings appearing in my console and does no harm.

Bonus

If you have multiple builds to update and you are using Azure Devops, you can take advantage of “Task Groups”. This allows you to create a single build step which in turn executes a series of other build steps. Using the steps above, you can create a new Task Group to create a single build step to run the test script and make sure the files are copied to the correct location for analysis. For example I have the single build step below:

Which means I can then just call this single build step in all my builds

Leave a Reply

Your email address will not be published. Required fields are marked *