{"id":12665,"date":"2017-01-11T10:59:29","date_gmt":"2017-01-11T18:59:29","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/?p=12665"},"modified":"2019-02-18T12:38:05","modified_gmt":"2019-02-18T19:38:05","slug":"code-coverage-now-available-for-powershell-core","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/code-coverage-now-available-for-powershell-core\/","title":{"rendered":"Code Coverage now available for PowerShell Core!"},"content":{"rendered":"<p>This is the first of a series of posts on PowerShell Core and the tools we use to test it. If you\u2019ve looked at the main project for PowerShell (<a href=\"https:\/\/github.com\/PowerShell\/PowerShell\">https:\/\/github.com\/PowerShell\/PowerShell<\/a>, you may have noticed a new badge down in the Build status of nightly builds:<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/badge.jpg\"><img decoding=\"async\" width=\"271\" height=\"82\" class=\"alignnone size-full wp-image-12675\" alt=\"badge\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/badge.jpg\" \/><\/a><\/p>\n<p>We are supplying code coverage numbers for our test pass via the OpenCover project (<a href=\"https:\/\/github.com\/OpenCover\/opencover\">https:\/\/github.com\/OpenCover\/opencover<\/a>) and we visualize our code coverage percentage via coveralls.io (<a href=\"https:\/\/coveralls.io\/github\/PowerShell\/PowerShell?branch=master\">https:\/\/coveralls.io\/github\/PowerShell\/PowerShell?branch=master<\/a>).\u00a0This means you can see some details about our testing and how much of PowerShell is covered by our test code.<\/p>\n<p>You can get your own coverage numbers easily via our OpenCover module which may be found in the &lt;RepoRoot&gt;test\/tools\/OpenCover directory.\u00a0To generate a code coverage report, you need to create a build which supports code coverage.\u00a0Currently, that\u2019s only available on Windows, but we do have an easy way to get it:<\/p>\n<p>(All of these commands assume that you are at the root of the PowerShell repo)<\/p>\n<pre># create a code coverage build.\nPS&gt; Start-PSBuild -Configuration CodeCoverage -Publish\n\n# Now that you have a build, save away the build location\nPS&gt; $psdir = split-path -parent (get-psoutput)\n\n# Import the OpenCover Module\nPS&gt; Import-module $pwd\/test\/tools\/OpenCover\n\n# install the opencover package\nPS&gt; Install-OpenCover $env:TEMP\n\n# now invoke a coverage test run\nPS&gt; Invoke-OpenCover -OutputLog Coverage.xml -test $PWD\/test\/powershell -OpenCoverPath $env:Temp\/OpenCover -PowerShellExeDirectory $psdir\n\n<\/pre>\n<p>If you want to get code coverage for only the tests that we run in our Continuous Integration (CI) environment, add the parameter -CIOnly.\u00a0Then you\u2019ll need to wait for a bit (on my system and using -CIOnly, it takes about 2.5 hours to run).<\/p>\n<h2>Looking at the Data<\/h2>\n<p>The OpenCover module can also help you visualize the results from a very high level.<\/p>\n<pre># first collect the coverage data with the Get-CodeCoverage cmdlet\nPS&gt; $coverData = Get-CodeCoverage .\\Coverage.xml\n# here\u2019s the coverage summary\nPS&gt; $coverData.CoverageSummary\nNumSequencePoints\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 309755\nVisitedSequencePoints\u00a0\u00a0 : 123779\nNumBranchPoints\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0: 105816\nVisitedBranchPoints\u00a0\u00a0\u00a0\u00a0 : 39842\nSequenceCoverage\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 39.96\nBranchCoverage\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 37.65\nMaxCyclomaticComplexity : 398\nMinCyclomaticComplexity : 1\nVisitedClasses\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 2005\nNumClasses\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 3309\nVisitedMethods\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 14912\nNumMethods\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : 33910\n\n# you can look at coverage data based on the assembly\nPS&gt; $coverData.Assembly | ft AssemblyName, Branch, Sequence\n\nAssemblyName\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Branch Sequence\n------------\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ------ --------\npowershell\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0100\u00a0\u00a0\u00a0 100\nMicrosoft.PowerShell.CoreCLR.AssemblyLoadContext 45.12\u00a0 94.75\nMicrosoft.PowerShell.ConsoleHost\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 22.78\u00a0 23.21\nSystem.Management.Automation\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 41.18\u00a0 42.96\nMicrosoft.PowerShell.CoreCLR.Eventing\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 23.33\u00a0 28.57\nMicrosoft.PowerShell.Security\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 12.62\u00a0 14.43\nMicrosoft.PowerShell.Commands.Management\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 14.69\u00a0 16.76\nMicrosoft.PowerShell.Commands.Utility\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 52.72\u00a0 54.40\nMicrosoft.WSMan.Management\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.36\u00a0\u00a0 0.65\nMicrosoft.WSMan.Runtime\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 100\u00a0\u00a0\u00a0 100\nMicrosoft.PowerShell.Commands.Diagnostics\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 42.99\u00a0 46.62\nMicrosoft.PowerShell.LocalAccounts\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\u00a0\u00a0\u00a0\u00a0\u00a0 0\nMicrosoft.PowerShell.PSReadLine\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6.98\u00a0\u00a0 9.86<\/pre>\n<p>I&#8217;m not going to go through all the different properties that are reported, we&#8217;ll take a closer look at\u00a0those in future posts.\u00a0\u00a0The Get-CoverageData cmdlet is still fairly rudimentary, but it will provide <em>some<\/em> details. This is part of our public repo, so I encourage you to enhance it and log issues if you find them!<\/p>\n<h3>Better Coverage Visualization<\/h3>\n<p>Another way to view coverage data is via the ReportGenerator package, which creates HTML reports and provides <em>much<\/em> more details about the coverage. The ReportGenerator package is available via the <span>find-package<\/span> cmdlet in the PackageManagement module. The following will install the package, and show how to run it:<\/p>\n<pre># find and install the report generator package\nPS&gt; find-package ReportGenerator -ProviderName nuget -Source <a href=\"https:\/\/nuget.org\/api\/v2\">https:\/\/nuget.org\/api\/v2<\/a> | install-package -Scope CurrentUser\nPS&gt; $ReportGenExe = \u201c$HOME\\AppData\\Local\\PackageManagement\\NuGet\\Packages\\ReportGenerator.2.5.2\\tools\\ReportGenerator.exe\u201d\n# invoke the report generator and create the report in c:\\temp\\Coverage\nPS&gt; &amp; $ReportGenExe -reports:Coverage.xml -targetdir:c:\\temp\\Coverage<\/pre>\n<p>Now that you\u2019ve created the reports, you can visualize them with your browser.<\/p>\n<pre>PS&gt; invoke-item C:\\temp\\Coverage\\index.htm<\/pre>\n<p>Click on the \u201cEnable filtering button\u201d, and then \u201cCollapse all\u201d and you should see something similar to:<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/coverage1.jpg\"><img decoding=\"async\" width=\"300\" height=\"153\" class=\"alignnone wp-image-12685\" alt=\"coverage1\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/coverage1-300x153.jpg\" srcset=\"https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage1-300x153.jpg 300w, https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage1-768x391.jpg 768w, https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage1.jpg 862w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>You can then drill in on what interests you (Microsoft.PowerShell.Commands.Utility, for example)<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/coverage2.jpg\"><img decoding=\"async\" width=\"300\" height=\"22\" class=\"alignnone size-medium wp-image-12695\" alt=\"coverage2\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2017\/01\/coverage2-300x22.jpg\" srcset=\"https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage2-300x22.jpg 300w, https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage2-768x57.jpg 768w, https:\/\/devblogs.microsoft.com\/powershell\/wp-content\/uploads\/sites\/30\/2017\/01\/coverage2.jpg 860w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Of course, there\u2019s a lot more detail to discover, and I encourage you to poke around. In my next post, I\u2019ll go through an entire workflow:<\/p>\n<ul>\n<li>Select an area for improvement<\/li>\n<li>Create new tests<\/li>\n<li>Gather new coverage data<\/li>\n<li>Compare results from previous runs<\/li>\n<\/ul>\n<p>I\u2019ll target something specific (a cmdlet) and show how to determine the gaps and how to fill them.<\/p>\n<h2>Call To Action!<\/h2>\n<p>Now that you see how easily you can generate code coverage data, this is a great opportunity to provide some additional coverage and increase the quality of our releases. If you see some area which you\u2019re passionate about\u00a0or notice an area which you would like to measure better, it\u2019s a great way to provide improved coverage. As you create new PRs, you can\u00a0aim for high coverage in your new functionality (85-90%), and now you can measure it!<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the first of a series of posts on PowerShell Core and the tools we use to test it. If you\u2019ve looked at the main project for PowerShell (https:\/\/github.com\/PowerShell\/PowerShell, you may have noticed a new badge down in the Build status of nightly builds: We are supplying code coverage numbers for our test pass [&hellip;]<\/p>\n","protected":false},"author":612,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-12665","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>This is the first of a series of posts on PowerShell Core and the tools we use to test it. If you\u2019ve looked at the main project for PowerShell (https:\/\/github.com\/PowerShell\/PowerShell, you may have noticed a new badge down in the Build status of nightly builds: We are supplying code coverage numbers for our test pass [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/12665","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/612"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=12665"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/12665\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=12665"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=12665"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=12665"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}