From c03fdef0525bd2eee5863d4e2cc846b176b44b3b Mon Sep 17 00:00:00 2001 From: Daan Jonkers Date: Thu, 19 Oct 2017 15:46:10 +0200 Subject: [PATCH 1/5] Added detailed code coverage. Per sourcefile a line counter and each line covered or missed numbers. --- Functions/Coverage.Tests.ps1 | 25 +++++++++ Functions/Coverage.ps1 | 85 ++++++++++++++++++++++++++++- Pester.psm1 | 9 +++- report.xsd | 102 +++++++++++++++++++++++++++++++++++ 4 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 report.xsd diff --git a/Functions/Coverage.Tests.ps1 b/Functions/Coverage.Tests.ps1 index a0a0d029b..6389bb915 100644 --- a/Functions/Coverage.Tests.ps1 +++ b/Functions/Coverage.Tests.ps1 @@ -83,6 +83,31 @@ InModuleScope Pester { Exit-CoverageAnalysis -PesterState $testState } + Context 'Entire file detailed coverage' { + $testState = New-PesterState -Path $root + + # Path deliberately duplicated to make sure the code doesn't produce multiple breakpoints for the same commands + Enter-CoverageAnalysis -CodeCoverage "$root\TestScript.ps1", "$root\TestScript.ps1" -PesterState $testState + + It 'Has the proper number of breakpoints defined' { + $testState.CommandCoverage.Count | Should Be 7 + } + + $null = & "$root\TestScript.ps1" + $coverageReport = Get-CoverageReport -PesterState $testState + + It 'JaCoCo report must be correct'{ + [String]$jaCoCoReportXml = Get-JaCoCoReportXml -PesterState $testState -CoverageReport $coverageReport -DetailedCodeCoverage + $jaCoCoReportXml = $jaCoCoReportXml -replace 'Pester \([^\)]*','Pester (date' + $jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""' + $jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""' + $jaCoCoReportXml = $jaCoCoReportXml -replace '\n','' + $jaCoCoReportXml = $jaCoCoReportXml.Replace($root,'') + $jaCoCoReportXml | should be '' + } + Exit-CoverageAnalysis -PesterState $testState + } + Context 'Single function with missed commands' { $testState = New-PesterState -Path $root diff --git a/Functions/Coverage.ps1 b/Functions/Coverage.ps1 index ff3e8ada3..4b30d7b44 100644 --- a/Functions/Coverage.ps1 +++ b/Functions/Coverage.ps1 @@ -488,6 +488,7 @@ function Get-CoverageReport $missedCommands = @(Get-CoverageMissedCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) $hitCommands = @(Get-CoverageHitCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) + $allCommands = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command, Breakpoint) $analyzedFiles = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] -ExpandProperty File -Unique) $fileCount = $analyzedFiles.Count @@ -500,6 +501,7 @@ function Get-CoverageReport NumberOfCommandsMissed = $missedCommands.Count MissedCommands = $missedCommands HitCommands = $hitCommands + AllCommands = $allCommands AnalyzedFiles = $analyzedFiles } } @@ -580,7 +582,9 @@ function Get-JaCoCoReportXml { [parameter(Mandatory=$true)] $PesterState, [parameter(Mandatory=$true)] - [object] $CoverageReport + [object] $CoverageReport, + + [Switch]$DetailedCodeCoverage ) if ($null -eq $CoverageReport -or ($pester.Show -eq [Pester.OutputTypes]::None) -or $CoverageReport.NumberOfCommandsAnalyzed -eq 0) @@ -610,6 +614,11 @@ function Get-JaCoCoReportXml { $jaCoCoReport += "`n" $jaCoCoReport += "`n" $jaCoCoReport += "`n" + + if ($DetailedCodeCoverage) + { + $jaCoCoReport += "`n" + } $jaCoCoReport += "`n" $jaCoCoReport += "`n" $jaCoCoReport += "`n" @@ -620,6 +629,80 @@ function Get-JaCoCoReportXml { $jaCoCoReportXml.report.name = "Pester ($now)" $jaCoCoReportXml.report.sessioninfo.start=$startTime.ToString() $jaCoCoReportXml.report.sessioninfo.dump=$endTime.ToString() + + if ($DetailedCodeCoverage) + { + + $fileName = ""; + $lineNr = -1; + $report = $jaCoCoReportXml.ChildNodes[1] + $package = $report.ChildNodes[1] + $mi = 0 + $ci = 0 + $missed = 0 + $covered = 0 + $line = $null + foreach($row in $CoverageReport.AllCommands) + { + if ($sourceName -ne $row.File) + { + $xmlFile = $jaCoCoReportXml.CreateElement("sourcefile") + $xmlName = $jaCoCoReportXml.CreateAttribute("name") + $xmlName.value = $row.File + $null = $xmlFile.Attributes.Append($xmlName) + $null = $package.AppendChild($xmlFile) + $sourceName = $row.File + $lineNr = -1; + $counter = $jaCoCoReportXml.CreateElement("counter") + + $missed = 0 + $covered = 0 + + $typeCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("type")) + $typeCounter.Value = "LINE" + + $miCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("missed")) + $miCounter.value = $missed + + $ciCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("covered")) + $ciCounter.value = $covered + + $null = $xmlFile.AppendChild($counter) + } + + if ($lineNr -ne $row.Line) + { + $line = $jaCoCoReportXml.CreateElement("line") + $nr = $jaCoCoReportXml.CreateAttribute("nr") + $nr.value = $row.Line + $mi = 0 + $ci = 0 + $null = $line.Attributes.Append($nr) + $ciLine = $line.Attributes.Append($jaCoCoReportXml.CreateAttribute("ci")) + $ciLine.value = 0 + $miLine = $line.Attributes.Append($jaCoCoReportXml.CreateAttribute("mi")) + $miLine.value = 0 + $null = $xmlFile.InsertBefore($line, $counter) + $lineNr = $row.Line + } + + if ($row.Breakpoint.HitCount -eq 0) + { + $mi += 1 + $miLine.value = $mi + $missed += 1 + $miCounter.value = $missed + } + else + { + $ci += 1 + $ciLine.value = $ci + $covered += 1 + $ciCounter.value = $covered + } + } + } + $jaCoCoReportXml.report.counter[0].missed = $CoverageReport.MissedCommands.Count.ToString() $jaCoCoReportXml.report.counter[0].covered = $CoverageReport.HitCommands.Count.ToString() $jaCoCoReportXml.report.counter[1].missed = $missedLines.ToString() diff --git a/Pester.psm1 b/Pester.psm1 index 6226e9807..ccf895464 100644 --- a/Pester.psm1 +++ b/Pester.psm1 @@ -761,6 +761,8 @@ New-PesterOption [ValidateSet('JaCoCo')] [String]$CodeCoverageOutputFileFormat = "JaCoCo", + [Switch]$DetailedCodeCoverage = $false, + [Switch]$Strict, [Parameter(Mandatory = $true, ParameterSetName = 'NewOutputSet')] @@ -856,10 +858,13 @@ New-PesterOption $pester | Write-PesterReport $coverageReport = Get-CoverageReport -PesterState $pester - Write-CoverageReport -CoverageReport $coverageReport + if ($DetailedCodeCoverage -eq $false) + { + Write-CoverageReport -CoverageReport $coverageReport + } if ((& $script:SafeCommands['Get-Variable'] -Name CodeCoverageOutputFile -ValueOnly -ErrorAction $script:IgnoreErrorPreference) ` -and (& $script:SafeCommands['Get-Variable'] -Name CodeCoverageOutputFileFormat -ValueOnly -ErrorAction $script:IgnoreErrorPreference) -eq 'JaCoCo') { - $jaCoCoReport = Get-JaCoCoReportXml -PesterState $pester -CoverageReport $coverageReport + $jaCoCoReport = Get-JaCoCoReportXml -PesterState $pester -CoverageReport $coverageReport -DetailedCodeCoverage:$DetailedCodeCoverage $jaCoCoReport | & $SafeCommands['Out-File'] $CodeCoverageOutputFile -Encoding utf8 } Exit-CoverageAnalysis -PesterState $pester diff --git a/report.xsd b/report.xsd new file mode 100644 index 000000000..b47e1586b --- /dev/null +++ b/report.xsd @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 03f15c4d4819fa366c34eba9ce705da941db31f8 Mon Sep 17 00:00:00 2001 From: Daan Jonkers Date: Fri, 20 Oct 2017 00:59:29 +0200 Subject: [PATCH 2/5] Added CodeCoverage parameter to Describe. If the -DetailedCodeCoverage switch is on then the CodeCoverage parameters of the Describe parts will be used for code coverage. --- Functions/Coverage.ps1 | 60 +++++++++++++++++++-------------------- Functions/Describe.ps1 | 23 ++++++++++++++- Functions/PesterState.ps1 | 5 ++++ Pester.Tests.ps1 | 4 +-- Pester.psm1 | 42 +++++++++++++++++++++++---- 5 files changed, 95 insertions(+), 39 deletions(-) diff --git a/Functions/Coverage.ps1 b/Functions/Coverage.ps1 index 4b30d7b44..c4dd0a437 100644 --- a/Functions/Coverage.ps1 +++ b/Functions/Coverage.ps1 @@ -488,7 +488,7 @@ function Get-CoverageReport $missedCommands = @(Get-CoverageMissedCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) $hitCommands = @(Get-CoverageHitCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) - $allCommands = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command, Breakpoint) + $allCommands = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command, Breakpoint) $analyzedFiles = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] -ExpandProperty File -Unique) $fileCount = $analyzedFiles.Count @@ -501,7 +501,7 @@ function Get-CoverageReport NumberOfCommandsMissed = $missedCommands.Count MissedCommands = $missedCommands HitCommands = $hitCommands - AllCommands = $allCommands + AllCommands = $allCommands AnalyzedFiles = $analyzedFiles } } @@ -641,38 +641,38 @@ function Get-JaCoCoReportXml { $ci = 0 $missed = 0 $covered = 0 - $line = $null + $line = $null foreach($row in $CoverageReport.AllCommands) { if ($sourceName -ne $row.File) { - $xmlFile = $jaCoCoReportXml.CreateElement("sourcefile") + $xmlFile = $jaCoCoReportXml.CreateElement("sourcefile") $xmlName = $jaCoCoReportXml.CreateAttribute("name") $xmlName.value = $row.File - $null = $xmlFile.Attributes.Append($xmlName) + $null = $xmlFile.Attributes.Append($xmlName) $null = $package.AppendChild($xmlFile) $sourceName = $row.File $lineNr = -1; - $counter = $jaCoCoReportXml.CreateElement("counter") + $counter = $jaCoCoReportXml.CreateElement("counter") - $missed = 0 - $covered = 0 + $missed = 0 + $covered = 0 - $typeCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("type")) - $typeCounter.Value = "LINE" + $typeCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("type")) + $typeCounter.Value = "LINE" $miCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("missed")) - $miCounter.value = $missed + $miCounter.value = $missed $ciCounter = $counter.Attributes.Append($jaCoCoReportXml.CreateAttribute("covered")) $ciCounter.value = $covered - $null = $xmlFile.AppendChild($counter) + $null = $xmlFile.AppendChild($counter) } - if ($lineNr -ne $row.Line) - { - $line = $jaCoCoReportXml.CreateElement("line") + if ($lineNr -ne $row.Line) + { + $line = $jaCoCoReportXml.CreateElement("line") $nr = $jaCoCoReportXml.CreateAttribute("nr") $nr.value = $row.Line $mi = 0 @@ -681,25 +681,25 @@ function Get-JaCoCoReportXml { $ciLine = $line.Attributes.Append($jaCoCoReportXml.CreateAttribute("ci")) $ciLine.value = 0 $miLine = $line.Attributes.Append($jaCoCoReportXml.CreateAttribute("mi")) - $miLine.value = 0 - $null = $xmlFile.InsertBefore($line, $counter) + $miLine.value = 0 + $null = $xmlFile.InsertBefore($line, $counter) $lineNr = $row.Line - } - - if ($row.Breakpoint.HitCount -eq 0) - { - $mi += 1 + } + + if ($row.Breakpoint.HitCount -eq 0) + { + $mi += 1 $miLine.value = $mi - $missed += 1 + $missed += 1 $miCounter.value = $missed - } - else - { - $ci += 1 + } + else + { + $ci += 1 $ciLine.value = $ci - $covered += 1 - $ciCounter.value = $covered - } + $covered += 1 + $ciCounter.value = $covered + } } } diff --git a/Functions/Describe.ps1 b/Functions/Describe.ps1 index 629aca79f..23e70b00e 100644 --- a/Functions/Describe.ps1 +++ b/Functions/Describe.ps1 @@ -25,6 +25,13 @@ Optional parameter containing an array of strings. When calling Invoke-Pester, it is possible to specify a -Tag parameter which will only execute Describe blocks containing the same Tag. +.PARAMETER CodeCoverage +Adds a code coverage report to the Pester tests. Takes strings or hash table values. + +A code coverage report lists the lines of code that did and did not run during +a Pester test. This report does not tell whether code was tested; only whether +the code ran during the test. + .EXAMPLE function Add-Numbers($a, $b) { return $a + $b @@ -69,6 +76,8 @@ about_TestDrive [Alias('Tags')] [string[]] $Tag=@(), + [object[]] $CodeCoverage = @(), + [Parameter(Position = 1)] [ValidateNotNull()] [ScriptBlock] $Fixture = $(Throw "No test script block is provided. (Have you put the open curly brace on the next line?)") @@ -81,7 +90,17 @@ about_TestDrive $script:mockTable = @{} } - DescribeImpl @PSBoundParameters -CommandUsed 'Describe' -Pester $Pester -DescribeOutputBlock ${function:Write-Describe} -TestOutputBlock ${function:Write-PesterResult} + if ($Pester.FindCodeCoverage) + { + foreach($cc in $CodeCoverage) + { + $Pester.CodeCoverage += $cc + } + } + else + { + DescribeImpl @PSBoundParameters -CommandUsed 'Describe' -Pester $Pester -DescribeOutputBlock ${function:Write-Describe} -TestOutputBlock ${function:Write-PesterResult} + } } function DescribeImpl { @@ -92,6 +111,8 @@ function DescribeImpl { [Alias('Tags')] $Tag=@(), + [object[]] $CodeCoverage = @(), + [Parameter(Position = 1)] [ValidateNotNull()] [ScriptBlock] $Fixture = $(Throw "No test script block is provided. (Have you put the open curly brace on the next line?)"), diff --git a/Functions/PesterState.ps1 b/Functions/PesterState.ps1 index 85ab4ea51..5945dd57b 100644 --- a/Functions/PesterState.ps1 +++ b/Functions/PesterState.ps1 @@ -52,6 +52,9 @@ function New-PesterState $script:Show = $Show $script:InTest = $false + $script:FindCodeCoverage = $false + $script:CodeCoverage = @() + $script:TestResult = @() $script:TotalCount = 0 @@ -319,6 +322,8 @@ function New-PesterState "TestResult", "SessionState", "CommandCoverage", + "FindCodeCoverage", + "CodeCoverage", "Strict", "Show", "Time", diff --git a/Pester.Tests.ps1 b/Pester.Tests.ps1 index 6455f5134..4c99a239d 100644 --- a/Pester.Tests.ps1 +++ b/Pester.Tests.ps1 @@ -4,8 +4,8 @@ $manifestPath = (Join-Path $here 'Pester.psd1') $changeLogPath = (Join-Path $here 'CHANGELOG.md') # DO NOT CHANGE THIS TAG NAME; IT AFFECTS THE CI BUILD. - -Describe -Tags 'VersionChecks' "Pester manifest and changelog" { +# +Describe -Tags 'VersionChecks' -CodeCoverage '.\Pester.psm1' "Pester manifest and changelog" { $script:manifest = $null $script:tagVersion = $null $script:tagVersionShort = $null diff --git a/Pester.psm1 b/Pester.psm1 index ccf895464..b8ed0e365 100644 --- a/Pester.psm1 +++ b/Pester.psm1 @@ -586,6 +586,9 @@ Default vaule is: JaCoCo. Currently supported formats are: - JaCoCo - this XML file format is compatible with the VSTS/TFS +.PARAMETER DetailedCodeCoverage +Add the sourcefile names and lines covered and missed to the codecoverage file. + .PARAMETER Strict Makes Pending and Skipped tests to Failed tests. Useful for continuous integration where you need to make sure all tests passed. @@ -761,7 +764,7 @@ New-PesterOption [ValidateSet('JaCoCo')] [String]$CodeCoverageOutputFileFormat = "JaCoCo", - [Switch]$DetailedCodeCoverage = $false, + [Switch]$DetailedCodeCoverage = $false, [Switch]$Strict, @@ -807,7 +810,6 @@ New-PesterOption try { - Enter-CoverageAnalysis -CodeCoverage $CodeCoverage -PesterState $pester Write-PesterStart $pester $Script $invokeTestScript = { @@ -826,6 +828,34 @@ New-PesterOption $testScripts = @(ResolveTestScripts $Script) + + if ($DetailedCodeCoverage) + { + $pester.FindCodeCoverage = $true + $pester.CodeCoverage = $CodeCoverage + + # find describe codecoverage here + foreach ($testScript in $testScripts) + { + try + { + do + { + & $invokeTestScript -Path $testScript.Path -Arguments $testScript.Arguments -Parameters $testScript.Parameters + } until ($true) + } + catch + { } + } + + + $pester.FindCodeCoverage = $false + $CodeCoverage = $pester.CodeCoverage + } + + + Enter-CoverageAnalysis -CodeCoverage $CodeCoverage -PesterState $pester + foreach ($testScript in $testScripts) { try @@ -858,10 +888,10 @@ New-PesterOption $pester | Write-PesterReport $coverageReport = Get-CoverageReport -PesterState $pester - if ($DetailedCodeCoverage -eq $false) - { - Write-CoverageReport -CoverageReport $coverageReport - } + if ($DetailedCodeCoverage -eq $false) + { + Write-CoverageReport -CoverageReport $coverageReport + } if ((& $script:SafeCommands['Get-Variable'] -Name CodeCoverageOutputFile -ValueOnly -ErrorAction $script:IgnoreErrorPreference) ` -and (& $script:SafeCommands['Get-Variable'] -Name CodeCoverageOutputFileFormat -ValueOnly -ErrorAction $script:IgnoreErrorPreference) -eq 'JaCoCo') { $jaCoCoReport = Get-JaCoCoReportXml -PesterState $pester -CoverageReport $coverageReport -DetailedCodeCoverage:$DetailedCodeCoverage From 5e352b81c23722d07929e169483956a9f3e385c7 Mon Sep 17 00:00:00 2001 From: Wojciech Sciesinski Date: Tue, 24 Jul 2018 02:20:23 +0200 Subject: [PATCH 3/5] A compatibility with PSCore 6.x correction and merging upstream error correction --- Functions/Coverage.Tests.ps1 | 10 ++++++---- Pester.Tests.ps1 | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Functions/Coverage.Tests.ps1 b/Functions/Coverage.Tests.ps1 index f53b46935..f0bcdfe6b 100644 --- a/Functions/Coverage.Tests.ps1 +++ b/Functions/Coverage.Tests.ps1 @@ -88,7 +88,8 @@ InModuleScope Pester { $jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""' $jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""' $jaCoCoReportXml = $jaCoCoReportXml -replace "$([System.Environment]::NewLine)",'' - $jaCoCoReportXml | should -be '' + [String]$ReferenceReport = [String]'' + $jaCoCoReportXml | should -Be $ReferenceReport } Exit-CoverageAnalysis -PesterState $testState } @@ -100,7 +101,7 @@ InModuleScope Pester { Enter-CoverageAnalysis -CodeCoverage "$root\TestScript.ps1", "$root\TestScript.ps1" -PesterState $testState It 'Has the proper number of breakpoints defined' { - $testState.CommandCoverage.Count | Should Be 7 + $testState.CommandCoverage.Count | Should -Be 7 } $null = & "$root\TestScript.ps1" @@ -111,9 +112,10 @@ InModuleScope Pester { $jaCoCoReportXml = $jaCoCoReportXml -replace 'Pester \([^\)]*','Pester (date' $jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""' $jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""' - $jaCoCoReportXml = $jaCoCoReportXml -replace '\n','' + $jaCoCoReportXml = $jaCoCoReportXml -replace "$([System.Environment]::NewLine)",'' $jaCoCoReportXml = $jaCoCoReportXml.Replace($root,'') - $jaCoCoReportXml | should be '' + [String]$ReferenceReport = "{0}{1}{2}" -f [String]'' + $jaCoCoReportXml | should -Be $ReferenceReport } Exit-CoverageAnalysis -PesterState $testState } diff --git a/Pester.Tests.ps1 b/Pester.Tests.ps1 index 4eba289cb..53d138a9e 100644 --- a/Pester.Tests.ps1 +++ b/Pester.Tests.ps1 @@ -7,7 +7,7 @@ $changeLogPath = (Join-Path $here 'CHANGELOG.md') # DO NOT CHANGE THIS TAG NAME; IT AFFECTS THE CI BUILD. # -Describe -Tags 'VersionChecks' -CodeCoverage '.\Pester.psm1' "Pester manifest and changelog" { +Describe -Tags 'VersionChecks' "Pester manifest and changelog" { $script:manifest = $null $script:tagVersion = $null $script:tagVersionShort = $null From c3d3dba416c6f1a3e807627e496b9cbc2a17a7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20D=C3=A9moulins?= Date: Sun, 7 Oct 2018 17:46:39 +0200 Subject: [PATCH 4/5] More comprehensive JaCoCo support --- Functions/Coverage.Tests.ps1 | 70 +++------ Functions/Coverage.ps1 | 296 ++++++++++++++++++++++------------- Functions/Describe.ps1 | 23 +-- Functions/PesterState.ps1 | 5 - Pester.Tests.ps1 | 2 +- Pester.psm1 | 41 +---- report.dtd | 8 +- report.xsd | 102 ------------ 8 files changed, 222 insertions(+), 325 deletions(-) delete mode 100644 report.xsd diff --git a/Functions/Coverage.Tests.ps1 b/Functions/Coverage.Tests.ps1 index f0bcdfe6b..f6b903be6 100644 --- a/Functions/Coverage.Tests.ps1 +++ b/Functions/Coverage.Tests.ps1 @@ -22,6 +22,10 @@ InModuleScope Pester { 'I am functionOne' NestedFunction } + + if ($false) { 'I cannot get called.' } + + Invoke-Command { 'I get called.' } } function FunctionTwo @@ -47,7 +51,7 @@ InModuleScope Pester { Enter-CoverageAnalysis -CodeCoverage "$(Join-Path -Path $root -ChildPath TestScript.ps1)", "$(Join-Path -Path $root -ChildPath TestScript.ps1)", "$(Join-Path -Path $root -ChildPath TestScript2.ps1)" -PesterState $testState It 'Has the proper number of breakpoints defined' { - $testState.CommandCoverage.Count | Should -Be 8 + $testState.CommandCoverage.Count | Should -Be 12 } $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)" @@ -55,11 +59,11 @@ InModuleScope Pester { $coverageReport = Get-CoverageReport -PesterState $testState It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 7 + $coverageReport.NumberOfCommandsExecuted | Should -Be 10 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 8 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 12 } It 'Reports the proper number of analyzed files' { @@ -67,15 +71,16 @@ InModuleScope Pester { } It 'Reports the proper number of missed commands' { - $coverageReport.MissedCommands.Count | Should -Be 1 + $coverageReport.MissedCommands.Count | Should -Be 2 } It 'Reports the correct missed command' { - $coverageReport.MissedCommands[0].Command | Should -Be "'I am function two. I never get called.'" + $coverageReport.MissedCommands[0].Command | Should -Be "'I cannot get called.'" + $coverageReport.MissedCommands[1].Command | Should -Be "'I am function two. I never get called.'" } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 7 + $coverageReport.HitCommands.Count | Should -Be 10 } It 'Reports the correct hit command' { @@ -88,34 +93,8 @@ InModuleScope Pester { $jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""' $jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""' $jaCoCoReportXml = $jaCoCoReportXml -replace "$([System.Environment]::NewLine)",'' - [String]$ReferenceReport = [String]'' - $jaCoCoReportXml | should -Be $ReferenceReport - } - Exit-CoverageAnalysis -PesterState $testState - } - - Context 'Entire file detailed coverage' { - $testState = New-PesterState -Path $root - - # Path deliberately duplicated to make sure the code doesn't produce multiple breakpoints for the same commands - Enter-CoverageAnalysis -CodeCoverage "$root\TestScript.ps1", "$root\TestScript.ps1" -PesterState $testState - - It 'Has the proper number of breakpoints defined' { - $testState.CommandCoverage.Count | Should -Be 7 - } - - $null = & "$root\TestScript.ps1" - $coverageReport = Get-CoverageReport -PesterState $testState - - It 'JaCoCo report must be correct'{ - [String]$jaCoCoReportXml = Get-JaCoCoReportXml -PesterState $testState -CoverageReport $coverageReport -DetailedCodeCoverage - $jaCoCoReportXml = $jaCoCoReportXml -replace 'Pester \([^\)]*','Pester (date' - $jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""' - $jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""' - $jaCoCoReportXml = $jaCoCoReportXml -replace "$([System.Environment]::NewLine)",'' - $jaCoCoReportXml = $jaCoCoReportXml.Replace($root,'') - [String]$ReferenceReport = "{0}{1}{2}" -f [String]'' - $jaCoCoReportXml | should -Be $ReferenceReport + $jaCoCoReportXml = $jaCoCoReportXml.Replace($root.Replace('\', '/'), '') + $jaCoCoReportXml | should -be '' } Exit-CoverageAnalysis -PesterState $testState } @@ -161,26 +140,26 @@ InModuleScope Pester { Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath TestScript.ps1)"; Function = 'FunctionOne'} -PesterState $testState It 'Has the proper number of breakpoints defined' { - $testState.CommandCoverage.Count | Should -Be 5 + $testState.CommandCoverage.Count | Should -Be 9 } $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)" $coverageReport = Get-CoverageReport -PesterState $testState It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 5 + $coverageReport.NumberOfCommandsExecuted | Should -Be 8 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 5 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 9 } It 'Reports the proper number of missed commands' { - $coverageReport.MissedCommands.Count | Should -Be 0 + $coverageReport.MissedCommands.Count | Should -Be 1 } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 5 + $coverageReport.HitCommands.Count | Should -Be 8 } It 'Reports the correct hit command' { @@ -231,18 +210,18 @@ InModuleScope Pester { Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath *.ps1)"; Function = '*' } -PesterState $testState It 'Has the proper number of breakpoints defined' { - $testState.CommandCoverage.Count | Should -Be 6 + $testState.CommandCoverage.Count | Should -Be 10 } $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)" $coverageReport = Get-CoverageReport -PesterState $testState It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 5 + $coverageReport.NumberOfCommandsExecuted | Should -Be 8 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 6 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 10 } It 'Reports the proper number of analyzed files' { @@ -250,15 +229,16 @@ InModuleScope Pester { } It 'Reports the proper number of missed commands' { - $coverageReport.MissedCommands.Count | Should -Be 1 + $coverageReport.MissedCommands.Count | Should -Be 2 } It 'Reports the correct missed command' { - $coverageReport.MissedCommands[0].Command | Should -Be "'I am function two. I never get called.'" + $coverageReport.MissedCommands[0].Command | Should -Be "'I cannot get called.'" + $coverageReport.MissedCommands[1].Command | Should -Be "'I am function two. I never get called.'" } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 5 + $coverageReport.HitCommands.Count | Should -Be 8 } It 'Reports the correct hit command' { diff --git a/Functions/Coverage.ps1 b/Functions/Coverage.ps1 index 73123ab75..ae98e7f51 100644 --- a/Functions/Coverage.ps1 +++ b/Functions/Coverage.ps1 @@ -488,7 +488,6 @@ function Get-CoverageReport $missedCommands = @(Get-CoverageMissedCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) $hitCommands = @(Get-CoverageHitCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command) - $allCommands = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command, Breakpoint) $analyzedFiles = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] -ExpandProperty File -Unique) $fileCount = $analyzedFiles.Count @@ -501,7 +500,6 @@ function Get-CoverageReport NumberOfCommandsMissed = $missedCommands.Count MissedCommands = $missedCommands HitCommands = $hitCommands - AllCommands = $allCommands AnalyzedFiles = $analyzedFiles } } @@ -582,9 +580,7 @@ function Get-JaCoCoReportXml { [parameter(Mandatory=$true)] $PesterState, [parameter(Mandatory=$true)] - [object] $CoverageReport, - - [Switch]$DetailedCodeCoverage + [object] $CoverageReport ) if ($null -eq $CoverageReport -or ($pester.Show -eq [Pester.OutputTypes]::None) -or $CoverageReport.NumberOfCommandsAnalyzed -eq 0) @@ -592,126 +588,210 @@ function Get-JaCoCoReportXml { return } - $allCommands = $CoverageReport.MissedCommands + $CoverageReport.HitCommands - [long]$totalFunctions = ($allCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -Unique ).Count - [long]$hitFunctions = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -Unique ).Count - [long]$missedFunctions = $totalFunctions - $hitFunctions + $now = & $SafeCommands['Get-Date'] + $nineteenSeventy = & $SafeCommands['Get-Date'] -Date "01/01/1970" + [long] $endTime = [math]::Floor((New-TimeSpan -start $nineteenSeventy -end $now).TotalMilliseconds) + [long] $startTime = [math]::Floor($endTime - $PesterState.Time.TotalMilliseconds) - [long]$totalLines = ($allCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -Unique ).Count - [long]$hitLines = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -Unique ).Count - [long]$missedLines = $totalLines - $hitLines + $package = @{ + Classes = [ordered] @{ } + Instruction = @{ Missed = 0; Covered = 0 } + Line = @{ Missed = 0; Covered = 0 } + Method = @{ Missed = 0; Covered = 0 } + Class = @{ Missed = 0; Covered = 0 } + } - [long]$totalFiles = $CoverageReport.NumberOfFilesAnalyzed + foreach($command in $PesterState.CommandCoverage) + { + $file = $command.File + $function = $command.Function + if (!$function) { $function = '