SonarQube, unit tests and code coverage with a .NET Core project in TFS or Azure Devops
Published February 22, 2019
Principal Consultant
Magnus Timner
<p><em>*Note*</em></p>
<p><em>This will not work on Linux. Take a look at the open issue on GitHub: https://github.com/Microsoft/vstest/issues/981</em></p>
<p> </p>
<p><span style="font-size: 12pt;">SonarQube, UnitTests and CodeCoverage does not work with a .NET Core project out of the box in TFS and Azure DevOps. Here are the extra steps you have to do in your code and in your build:</span></p>
<p><span style="font-size: 18pt;"><strong>SonarQube build tasks</strong></span></p>
<p><span style="font-size: 12pt;">Get started by adding the three Sonar tasks – these steps should be added before build and after test.</span></p>
<p><img class="aligncenter size-full wp-image-4562" src="https://www.datocms-assets.com/15783/1572625023-sonar-1.png" alt="" width="705" height="457" /></p>
<h3><strong><span style="font-size: 14pt;">Project key and project name</span></strong></h3>
<p><span style="font-size: 12pt;">You have to provide a name and a key to identify your project in SonarQube.</span></p>
<p><span style="font-size: 12pt;">You also have an option to add additional properties under the advanced tab.</span><br />
<span style="font-size: 12pt;">Add the following if you. for example, would like to exclude files in the test and lib directories.</span></p>
<p><code><span style="font-size: 12pt;">sonar.exclusions=**/*test*</span></code></p>
<p><code><span style="font-size: 12pt;">sonar.exclusions=**/lib/**</span></code></p>
<p><img class="aligncenter size-full wp-image-4563" src="https://www.datocms-assets.com/15783/1572343594-sonarqube-2.png" alt="" width="1167" height="510" /></p>
<h3><strong><span style="font-size: 14pt;">Enable Code Coverage</span></strong></h3>
<p><span style="font-size: 12pt;">Enable code coverage in the test task to get that data to SonarQube.</span></p>
<p><code><span style="font-size: 12pt;">--collect "Code coverage"</span></code></p>
<p><img class="aligncenter size-full wp-image-4564" src="https://www.datocms-assets.com/15783/1572343614-sonarqube-3.png" alt="" width="1277" height="512" /></p>
<h3><strong><span style="font-size: 14pt;">Exceptions/strange stuff</span></strong></h3>
<p><span style="font-size: 12pt;">There are some “strange” things you also need to do to get the code coverage and unit tests working when you use .NET Core and SonarQube. I hope this is temporary.</span></p>
<h3><strong><span style="font-size: 14pt;">Trx and Coverage files</span></strong></h3>
<p><span style="font-size: 12pt;">Trx and Coverage files end up in a temporary folder outside of the build, you need to copy them to the $(Common.TestResultsDirectory) folder. Add the Copy Files task to do this.</span></p>
<p><img class="aligncenter size-full wp-image-4565" src="https://www.datocms-assets.com/15783/1572343659-sonarqube-4.png" alt="" width="1321" height="532" /></p>
<p><code><span style="font-size: 12pt;">$(Agent.HomeDirectory)\_work\_temp</span></code></p>
<p><code><span style="font-size: 12pt;">$(Common.TestResultsDirectory)</span></code></p>
<h3><strong><span style="font-size: 14pt;">Project Guids</span></strong></h3>
<p><span style="font-size: 12pt;">SonarQube requires project Guids, which is not part of .NET Core projects by default. We add this code below to each csproj file to be analyzed. Make sure to select a different Guid for each project.</span></p>
<p><span style="font-size: 12pt;"><code><PropertyGroup></code></span></p>
<p><span style="font-size: 12pt;"><code> <!-- SonarQube needs this --></code></span></p>
<p><span style="font-size: 12pt;"><code> <ProjectGuid>{E2CEBBAF-6DF7-41E9-815D-9AD4CF90C840}</ProjectGuid></code></span></p>
<p><span style="font-size: 12pt;"><code></PropertyGroup></code></span></p>
<h2><span style="font-size: 18pt;"><strong>The result in SonarQube</strong></span></h2>
<p>And we’re done! Here’s the final result in SonarQube:</p>
<p><img class="aligncenter size-full wp-image-4566" src="https://www.datocms-assets.com/15783/1572343675-sonarqube-5.png?auto=format&fit=max&ixlib=react-8.6.2&h=855&w=1446" alt="" width="1262" height="746" /></p>