{"id":68783,"date":"2023-05-18T07:04:05","date_gmt":"2023-05-18T15:04:05","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/devops\/?p=68783"},"modified":"2024-02-23T16:19:47","modified_gmt":"2024-02-24T00:19:47","slug":"publish-code-coverage-report-in-azure-devops-services-pipeline-execution-summary","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/publish-code-coverage-report-in-azure-devops-services-pipeline-execution-summary\/","title":{"rendered":"Publish Code Coverage Report in Azure DevOps Services pipeline execution summary"},"content":{"rendered":"<p>This blog content is compiled by\u00a0<a href=\"https:\/\/techcommunity.microsoft.com\/t5\/user\/viewprofilepage\/user-id\/645975\">@Ahetejaz<\/a>\u00a0from Azure DevOps CSS support team. He helped a customer in implementing Code Coverage report as part of Pipeline execution summary page in Azure DevOps Service.\u00a0<\/p>\n<p>Below screenshot shows the code coverage report published in pipeline summary page:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1.png\" alt=\"Image image1 1\" width=\"1498\" height=\"682\" class=\"alignnone size-full wp-image-68787\" srcset=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1.png 1498w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1-300x137.png 300w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1-1024x466.png 1024w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image1-1-768x350.png 768w\" sizes=\"(max-width: 1498px) 100vw, 1498px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2.png\" alt=\"Image image2\" width=\"1492\" height=\"410\" class=\"alignnone size-full wp-image-68789\" srcset=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2.png 1492w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2-300x82.png 300w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2-1024x281.png 1024w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image2-768x211.png 768w\" sizes=\"(max-width: 1492px) 100vw, 1492px\" \/><\/a><\/p>\n<h2>Steps to generate code coverage:<\/h2>\n<ul>\n<li>\n<p>Create .NET Core application using Visual Studio.<\/p>\n<\/li>\n<li>\n<p>From NuGet package download \u2018coverlet.msbuild\u2019.<\/p>\n<\/li>\n<\/ul>\n<p>Coverage tool can create coverage file required by either Jacoco or Cobertura.<\/p>\n<p>Jacoco or Cobertura can populate the data to code coverage tab in Azure Pipeline run (refer above screenshot).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3.png\" alt=\"Image image3\" width=\"1120\" height=\"84\" class=\"alignnone size-full wp-image-68792\" srcset=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3.png 1120w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3-300x23.png 300w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3-1024x77.png 1024w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image3-768x58.png 768w\" sizes=\"(max-width: 1120px) 100vw, 1120px\" \/><\/a><\/p>\n<p>\u2018coverlet.msbuild\u2019 is one such tool which can create such coverage to be used by the Cobertura and Jacoco.<\/p>\n<p>&#8211;\u00a0Pipeline\u00a0uses below tasks to generate code coverage report.<\/p>\n<p>trigger:<\/p>\n<p>&#8211;\u00a0none<\/p>\n<p>jobs:<\/p>\n<p>&#8211;\u00a0job:\u00a0Job_1<\/p>\n<p>\u00a0\u00a0displayName:\u00a0Agent\u00a0job\u00a01<\/p>\n<p>\u00a0\u00a0pool:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0vmImage:\u00a0windows-latest<\/p>\n<p>\u00a0\u00a0steps:<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0checkout:\u00a0self<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0task:\u00a0UseDotNet@2<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0displayName:\u00a0Net\u00a0Core\u00a0sdk\u00a02<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0inputs:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0includePreviewVersions:\u00a0true<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0task:\u00a0DotNetCoreCLI@2<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0inputs:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0command:\u00a0&#8216;build&#8217;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0projects:\u00a0&#8216;*&#42;\/&#42;.csproj&#8217;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0arguments:\u00a0&#8216;\/t:restore&#8217;<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0task:\u00a0DotNetCoreCLI@2<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0displayName:\u00a0Test<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0condition:\u00a0succeededOrFailed()<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0inputs:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0command:\u00a0test<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0projects:\u00a0&#8216;*&#42;\/&#42;.csproj\u00a0&#8216;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0arguments:\u00a0\/p:CollectCoverage=true\u00a0\/p:CoverletOutputFormat=cobertura\u00a0\/p:CoverletOutput=$(Build.SourcesDirectory)\/TestResults\/Coverage\/<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0task:\u00a0reportgenerator@4<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0displayName:\u00a0ReportGenerator<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0condition:\u00a0succeededOrFailed()<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0inputs:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reports:\u00a0$(Build.SourcesDirectory)\/TestResults\/Coverage\/coverage.cobertura.xml<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0targetdir:\u00a0$(Build.SourcesDirectory)\\coveragereport<\/p>\n<p>\u00a0\u00a0&#8211;\u00a0task:\u00a0PublishCodeCoverageResults@1<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0displayName:\u00a0Publish\u00a0code\u00a0coverage<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0condition:\u00a0always()<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0inputs:<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0codeCoverageTool:\u00a0Cobertura<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0summaryFileLocation:\u00a0$(Build.SourcesDirectory)\\coveragereport\\cobertura.xml<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reportDirectory:\u00a0$(Build.SourcesDirectory)\\coveragereport\\<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0additionalCodeCoverageFiles:\u00a0$(Build.SourcesDirectory)\\coveragereport*.html<\/p>\n<h2>Points to Remember:<\/h2>\n<p>1&#46; The feature to have code coverage as part of DevOps UI is under development. Reference link &#8211;\u00a0<a href=\"https:\/\/nam06.safelinks.protection.outlook.com\/?url=https:%2f%2fdevelopercommunity.visualstudio.com%2fidea%2f366142%2fsupport-vstest-coverage-code-coverage-build-result.html&amp;data=02%7c01%7cAhetejazahmad.Khan%40microsoft.com%7c335a3c8c604c44b202bb08d7f612f224%7c72f988bf86f141af91ab2d7cd011db47%7c1%7c0%7c637248433560209861&amp;sdata=z%2fGh3xes%2BDtXDPK%2BqSaOpZ%2Bbkc0AHkw%2fh39pmpBfzC4%3D&amp;reserved=0\" title=\"https:\/\/developercommunity.visualstudio.com\/idea\/366142\/support-vstest-coverage-code-coverage-build-result.html\">https:\/\/developercommunity.visualstudio.com\/idea\/366142\/support-vstest-coverage-code-coverage-build-result.html<\/a>\u00a0There is no fixed timeline as to when the feature would be available.<\/p>\n<p>2&#46; If we use .NET Core projects, then we could use .NET Core task which would give code coverage in the build logs. <strong><em>Not in DevOps UI<\/em><\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image4.png\" alt=\"Image image4\" width=\"511\" height=\"318\" class=\"alignnone size-full wp-image-68795\" srcset=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image4.png 511w, https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2024\/02\/image4-300x187.png 300w\" sizes=\"(max-width: 511px) 100vw, 511px\" \/><\/a><\/p>\n<p>3&#46; Publish code coverage result task supports coverage result formats such as Cobertura and JaCoCo. To use the task we would need to use a code coverage tool as part of the project solution. We may add a Nuget package to get the tool added to generate code coverage file required by either Cobertura or JaCoCo. Cobertura or JaCoCo could then populate the data to the code coverage tab. Coverlet.msbuild is one such tool which can create such coverage to be used by the Cobertura and JaCoCo.<\/p>\n<p>4&#46; Before using publish code coverage result task we might need to understand that this task comes with certain limitation as mentioned in the article &#8211;\u00a0<a href=\"https:\/\/github.com\/coverlet-coverage\/coverlet#quick-start\">https:\/\/github.com\/coverlet-coverage\/coverlet#quick-start<\/a><\/p>\n<ul>\n<li>Coverlet supports only SDK-style projects\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/msbuild\/how-to-use-project-sdk?view=vs-2019\">https:\/\/docs.microsoft.com\/en-us\/visualstudio\/msbuild\/how-to-use-project-sdk?view=vs-2019<\/a><\/li>\n<\/ul>\n<p>5&#46; For .NET Framework (4.7.2) project which does not use SDK style will not publish code coverage result in DevOps UI.<\/p>\n<p>6&#46;\u00a0For .NET Core project, we will be able to publish code coverage result using 3rd\u00a0party component mentioned in point 3. Also, we used an extra task \u2018ReportGenerator\u2019 which is <strong><em>NOT<\/em><\/strong> owned by Microsoft to publish the results. Support for this task will not be provided by Microsoft.<\/p>\n<p>Two link that might be handy for reference:<\/p>\n<p>&#8211;\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/msbuild\/how-to-use-project-sdk?view=vs-2019\">https:\/\/docs.microsoft.com\/en-us\/visualstudio\/msbuild\/how-to-use-project-sdk?view=vs-2019<br \/>\n<\/a>&#8211;\u00a0<a href=\"https:\/\/github.com\/coverlet-coverage\/coverlet\/blob\/master\/Documentation\/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test\">https:\/\/github.com\/coverlet-coverage\/coverlet\/blob\/master\/Documentation\/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test<\/a><\/p>\n<p>Cheers!!<\/p>\n<p>Ahmad<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Publish Code Coverage Report as part of the pipeline execution summary in Azure DevOps Services.<\/p>\n","protected":false},"author":148453,"featured_media":68832,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[253],"tags":[],"class_list":["post-68783","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-devops-server"],"acf":[],"blog_post_summary":"<p>Publish Code Coverage Report as part of the pipeline execution summary in Azure DevOps Services.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/68783","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/148453"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=68783"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/68783\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/68832"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=68783"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=68783"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=68783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}