{"id":1223,"date":"2017-10-12T10:00:27","date_gmt":"2017-10-12T08:00:27","guid":{"rendered":"http:\/\/tpodolak.com\/blog\/?p=1223"},"modified":"2017-10-12T00:13:46","modified_gmt":"2017-10-11T22:13:46","slug":"net-core-calculating-code-coverage-opencover-windows","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2017\/10\/12\/net-core-calculating-code-coverage-opencover-windows\/","title":{"rendered":".NET Core &#8211; calculating code coverage with OpenCover (on Windows)"},"content":{"rendered":"<h3>1. Introduction.<\/h3>\n<p>I&#8217;ve been struggling for some time to make <i>OpenCover<\/i> work with <i>.NET Core<\/i> projects, so I&#8217;ve decided to document a working example. This is basically an aggregation of hints and answers I found on the <i>Web<\/i> (especially in <a href=\"https:\/\/github.com\/OpenCover\/opencover\/issues\/601\">here<\/a>)<\/p>\n<h3>2. Working example.<\/h3>\n<p>If you run an <i>OpenCover<\/i> with the same arguments you were running it for a classic framework, you will end up with something like this<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs.png\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs.png\" alt=\"\" width=\"1122\" class=\"aligncenter size-full wp-image-1224\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs.png 1122w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs-150x97.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs-300x195.png 300w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/MissingPdbs-1024x665.png 1024w\" sizes=\"(max-width: 1122px) 100vw, 1122px\" \/><\/a> As you can see the coverage was not calculated and <i>OpenCover<\/i> is complaining about a missing <i>PDBs<\/i>. In order to fix that we have to do two things. First of all, we have to build the project with a full <i>PDBs<\/i><\/p>\n<pre lang=\"bash\">\r\ndotnet build \"PathToYourSolution.sln\" \/p:DebugType=Full\r\n<\/pre>\n<p>And then run <i>OpenCover<\/i> with and <i>-oldStyle<\/i> switch<\/p>\n<pre lang=\"bash\">\r\nOpenCover.Console.exe -target:\"C:\/Program Files\/dotnet\/dotnet.exe\" -targetargs:\"test \\\"PathToTestProject.csproj\\\" --configuration Debug --no-build\" -filter:\"+[*]* -[*.Tests*]*\" -oldStyle -register:user -output:\"OpenCover.xml\"\r\n<\/pre>\n<p>From now on, <i>OpenCover<\/i> recognizes <i>PDB<\/i> files and the code coverage is calculated correctly<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs.png\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs.png\" alt=\"\" width=\"1136\" class=\"aligncenter size-full wp-image-1225\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs.png 1136w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs-150x107.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs-300x214.png 300w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/OkPdbs-1024x729.png 1024w\" sizes=\"(max-width: 1136px) 100vw, 1136px\" \/><\/a><\/p>\n<h3>3. Cake script.<\/h3>\n<p>As we use a <i>Cake<\/i> as our build automation tool I&#8217;ve also prepared a sample script for generating a code coverage. The core part of the script looks as follows<\/p>\n<pre lang=\"csharp\">\r\n\/\/ rest of the code omitted for brevity\r\n\r\nTask(\"Build\")\r\n    .IsDependentOn(\"Restore-NuGet-Packages\")\r\n    .Does(() =>\r\n{\r\n    DotNetCoreBuild(paths.Files.Solution.ToString(), new DotNetCoreBuildSettings\r\n    {\r\n        Configuration = parameters.Configuration,\r\n        ArgumentCustomization = arg => arg.AppendSwitch(\"\/p:DebugType\",\"=\",\"Full\")\r\n    });\r\n});\r\n\r\nTask(\"Run-Tests\")\r\n    .IsDependentOn(\"Build\")\r\n    .Does(() =>\r\n{\r\n    var success = true;\r\n    var openCoverSettings = new OpenCoverSettings\r\n    {\r\n        OldStyle = true,\r\n        MergeOutput = true\r\n    }\r\n    .WithFilter(\"+[*]* -[*.Tests*]*\");\r\n\r\n    foreach(var project in paths.Files.TestProjects)\r\n    {\r\n        try \r\n        {\r\n            var projectFile = MakeAbsolute(project).ToString();\r\n            var dotNetTestSettings = new DotNetCoreTestSettings\r\n            {\r\n                Configuration = parameters.Configuration,\r\n                NoBuild = true\r\n            };\r\n\r\n            OpenCover(context => context.DotNetCoreTest(projectFile, dotNetTestSettings), paths.Files.TestCoverageOutput, openCoverSettings);\r\n        }\r\n        catch(Exception ex)\r\n        {\r\n            success = false;\r\n            Error(\"There was an error while running the tests\", ex);\r\n        }\r\n    }\r\n\r\n    ReportGenerator(paths.Files.TestCoverageOutput, paths.Directories.TestResults);\r\n\r\n    if(success == false)\r\n    {\r\n        throw new CakeException(\"There was an error while running the tests\");\r\n    }\r\n\r\n});\r\n<\/pre>\n<p>Notice that script is able to merge code coverage results from multiple test projects thanks to <i>MergeOutput<\/i> flag passed to <i>OpenCover<\/i>.<\/p>\n<p><a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report.png\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report.png\" alt=\"\" width=\"1243\" class=\"aligncenter size-full wp-image-1226\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report.png 1243w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report-150x63.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report-300x126.png 300w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/10\/net-core-calculating-code-coverage-on-windows\/Report-1024x431.png 1024w\" sizes=\"(max-width: 1243px) 100vw, 1243px\" \/><\/a><br \/>\nFull sources of that script (along with a <i>dotnet vstest<\/i> alternative approach) can be found <a href=\"https:\/\/github.com\/tpodolak\/Blog\/tree\/master\/NETCoreCodeCoverage\/Build\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction. I&#8217;ve been struggling for some time to make OpenCover work with .NET Core projects, so I&#8217;ve decided to document a working example. This is basically an aggregation of hints and answers I found on the Web (especially in here) 2. Working example. If you run an OpenCover with the same arguments you were [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[328],"tags":[329],"class_list":["post-1223","post","type-post","status-publish","format-standard","hentry","category-net-core","tag-opencover"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=1223"}],"version-history":[{"count":8,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1223\/revisions"}],"predecessor-version":[{"id":1234,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1223\/revisions\/1234"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=1223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=1223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=1223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}