diff --git a/build.ps1 b/build.ps1 index 4eb4ed477..2256e018e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -202,6 +202,7 @@ if ($Clean) { , ("$PSScriptRoot/src/schemas/JUnit4/*.xsd", "$PSScriptRoot/bin/schemas/JUnit4/") , ("$PSScriptRoot/src/schemas/NUnit25/*.xsd", "$PSScriptRoot/bin/schemas/NUnit25/") , ("$PSScriptRoot/src/schemas/NUnit3/*.xsd", "$PSScriptRoot/bin/schemas/NUnit3/") + , ("$PSScriptRoot/src/schemas/Cobertura/*.dtd", "$PSScriptRoot/bin/schemas/Cobertura/") , ("$PSScriptRoot/src/schemas/JaCoCo/*.dtd", "$PSScriptRoot/bin/schemas/JaCoCo/") , ("$PSScriptRoot/src/csharp/Pester/bin/$Configuration/net452/Pester.dll", "$PSScriptRoot/bin/bin/net452/") , ("$PSScriptRoot/src/csharp/Pester/bin/$Configuration/net452/Pester.pdb", "$PSScriptRoot/bin/bin/net452/") diff --git a/publish/filesToPublish.ps1 b/publish/filesToPublish.ps1 index 56fba4967..2397f8142 100644 --- a/publish/filesToPublish.ps1 +++ b/publish/filesToPublish.ps1 @@ -10,6 +10,7 @@ 'bin/netstandard2.0/Pester.pdb' 'en-US/about_Pester.help.txt' 'en-US/about_PesterConfiguration.help.txt' + 'schemas/Cobertura/coverage-loose.dtd' 'schemas/JaCoCo/report.dtd' 'schemas/JUnit4/junit_schema_4.xsd' 'schemas/NUnit25/nunit_schema_2.5.xsd' diff --git a/src/csharp/Pester/CodeCoverageConfiguration.cs b/src/csharp/Pester/CodeCoverageConfiguration.cs index ffcc3e10f..0309046ed 100644 --- a/src/csharp/Pester/CodeCoverageConfiguration.cs +++ b/src/csharp/Pester/CodeCoverageConfiguration.cs @@ -41,7 +41,7 @@ public static CodeCoverageConfiguration ShallowClone(CodeCoverageConfiguration c public CodeCoverageConfiguration() : base("CodeCoverage configuration.") { Enabled = new BoolOption("Enable CodeCoverage.", false); - OutputFormat = new StringOption("Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters", "JaCoCo"); + OutputFormat = new StringOption("Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura", "JaCoCo"); OutputPath = new StringOption("Path relative to the current directory where code coverage report is saved.", "coverage.xml"); OutputEncoding = new StringOption("Encoding of the output file.", "UTF8"); Path = new StringArrayOption("Directories or files to be used for code coverage, by default the Path(s) from general settings are used, unless overridden here.", new string[0]); diff --git a/src/en-US/about_PesterConfiguration.help.txt b/src/en-US/about_PesterConfiguration.help.txt index 5057e0042..76f3e437d 100644 --- a/src/en-US/about_PesterConfiguration.help.txt +++ b/src/en-US/about_PesterConfiguration.help.txt @@ -95,7 +95,7 @@ SECTIONS AND OPTIONS Type: bool Default value: $false - OutputFormat: Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters + OutputFormat: Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura Type: string Default value: 'JaCoCo' diff --git a/src/functions/Coverage.Plugin.ps1 b/src/functions/Coverage.Plugin.ps1 index 809e058c6..bf507a034 100644 --- a/src/functions/Coverage.Plugin.ps1 +++ b/src/functions/Coverage.Plugin.ps1 @@ -145,11 +145,11 @@ $configuration = $run.PluginConfiguration.Coverage - if ($configuration.OutputFormat -in 'JaCoCo', 'CoverageGutters') { - [xml] $jaCoCoReport = [xml] (Get-JaCoCoReportXml -CommandCoverage $breakpoints -TotalMilliseconds $totalMilliseconds -CoverageReport $coverageReport -Format $configuration.OutputFormat) - } - else { - throw "CodeCoverage.CoverageFormat '$($configuration.OutputFormat)' is not valid, please review your configuration." + $coverageXmlReport = switch ($configuration.OutputFormat) { + 'JaCoCo' { [xml](Get-JaCoCoReportXml -CommandCoverage $breakpoints -TotalMilliseconds $totalMilliseconds -CoverageReport $coverageReport -Format 'JaCoCo') } + 'CoverageGutters' { [xml](Get-JaCoCoReportXml -CommandCoverage $breakpoints -TotalMilliseconds $totalMilliseconds -CoverageReport $coverageReport -Format 'CoverageGutters') } + 'Cobertura' { [xml](Get-CoberturaReportXml -CoverageReport $coverageReport -TotalMilliseconds $totalMilliseconds) } + default { throw "CodeCoverage.CoverageFormat '$($configuration.OutputFormat)' is not valid, please review your configuration." } } $settings = [Xml.XmlWriterSettings] @{ @@ -163,7 +163,7 @@ $stringWriter = [Pester.Factory]::CreateStringWriter() $xmlWriter = [Xml.XmlWriter]::Create($stringWriter, $settings) - $jaCocoReport.WriteContentTo($xmlWriter) + $coverageXmlReport.WriteContentTo($xmlWriter) $xmlWriter.Flush() $stringWriter.Flush() @@ -216,7 +216,7 @@ } function Resolve-CodeCoverageConfiguration { - $supportedFormats = 'JaCoCo', 'CoverageGutters' + $supportedFormats = 'JaCoCo', 'CoverageGutters', 'Cobertura' if ($PesterPreference.CodeCoverage.OutputFormat.Value -notin $supportedFormats) { throw (Get-StringOptionErrorMessage -OptionPath 'CodeCoverage.OutputFormat' -SupportedValues $supportedFormats -Value $PesterPreference.CodeCoverage.OutputFormat.Value) } diff --git a/src/functions/Coverage.ps1 b/src/functions/Coverage.ps1 index 8548c3162..ddb6e7613 100644 --- a/src/functions/Coverage.ps1 +++ b/src/functions/Coverage.ps1 @@ -231,12 +231,12 @@ function Get-CodeCoverageFilePaths { $testsPattern = "*$($PesterPreference.Run.TestExtension.Value)" [string[]] $filteredFiles = @(foreach ($file in (& $SafeCommands['Get-ChildItem'] -LiteralPath $Paths -File -Recurse:$RecursePaths)) { - if (('.ps1', '.psm1') -contains $file.Extension -and ($IncludeTests -or $file.Name -notlike $testsPattern)) { - $file.FullName - } - }) + if (('.ps1', '.psm1') -contains $file.Extension -and ($IncludeTests -or $file.Name -notlike $testsPattern)) { + $file.FullName + } + }) - $uniqueFiles = & $SafeCommands['New-Object'] -TypeName 'System.Collections.Generic.HashSet[string]' -ArgumentList (,$filteredFiles) + $uniqueFiles = & $SafeCommands['New-Object'] -TypeName 'System.Collections.Generic.HashSet[string]' -ArgumentList (, $filteredFiles) return $uniqueFiles } @@ -452,6 +452,14 @@ function IsIgnoredCommand { return $true } + if ($PSVersionTable.PSVersion.Major -ge 5) { + if ($Command -is [System.Management.Automation.Language.CommandExpressionAst] -and + $Command.Expression[0] -is [System.Management.Automation.Language.BaseCtorInvokeMemberExpressionAst]) { + # Calls to inherited "base(...)" constructor does not trigger breakpoint or tracer hit, ignore. + return $true + } + } + return $false } @@ -804,9 +812,10 @@ function Get-JaCoCoReportXml { return [string]::Empty } - $now = & $SafeCommands['Get-Date'] - $nineteenSeventy = & $SafeCommands['Get-Date'] -Date "01/01/1970" - [long] $endTime = [math]::Floor((New-TimeSpan -start $nineteenSeventy -end $now).TotalMilliseconds) + # Report uses unix epoch time format (milliseconds since midnight 1/1/1970 UTC) + $nineteenSeventy = & $SafeCommands['New-Object'] 'System.DateTime' -ArgumentList @(1970, 1, 1, 0, 0, 0, [System.DateTimeKind]::Utc) + $now = [DateTime]::Now.ToUniversalTime() + [long] $endTime = [math]::Floor(($now - $nineteenSeventy).TotalMilliseconds) [long] $startTime = [math]::Floor($endTime - $TotalMilliseconds) $folderGroups = $CommandCoverage | & $SafeCommands["Group-Object"] -Property { @@ -1028,6 +1037,226 @@ function Get-JaCoCoReportXml { return $xml } +function Get-CoberturaReportXml { + param ( + [parameter(Mandatory = $true)] + [object] $CoverageReport, + [parameter(Mandatory = $true)] + [long] $TotalMilliseconds + ) + + if ($null -eq $CoverageReport -or $CoverageReport.NumberOfCommandsAnalyzed -eq 0) { + return [string]::Empty + } + + # Report uses unix epoch time format (milliseconds since midnight 1/1/1970 UTC) + $nineteenSeventy = & $SafeCommands['New-Object'] 'System.DateTime' -ArgumentList @(1970, 1, 1, 0, 0, 0, [System.DateTimeKind]::Utc) + $now = [DateTime]::Now.ToUniversalTime() + [long] $endTime = [math]::Floor(($now - $nineteenSeventy).TotalMilliseconds) + [long] $startTime = [math]::Floor($endTime - $TotalMilliseconds) + + $commonRoot = Get-CommonParentPath -Path $CoverageReport.AnalyzedFiles + + $allLines = [System.Collections.Generic.List[object]]@() + $allLines.AddRange($CoverageReport.MissedCommands) + $allLines.AddRange($CoverageReport.HitCommands) + $packages = @{} + foreach ($command in $allLines) { + $package = & $SafeCommands["Split-Path"] $command.File -Parent + if (!$packages[$package]) { + $packages[$package] = @{ + Classes = @{} + } + } + + $class = $command.File + if (!$packages[$package].Classes[$class]) { + $packages[$package].Classes[$class] = @{ + Methods = @{} + Lines = @{} + } + } + + if (!$packages[$package].Classes[$class].Lines[$command.Line]) { + $packages[$package].Classes[$class].Lines[$command.Line] = [ordered]@{ number = $command.Line ; hits = 0 } + } + $packages[$package].Classes[$class].Lines[$command.Line].hits += $command.HitCount + + $method = $command.Function + if (!$method) { + continue + } + + if (!$packages[$package].Classes[$class].Methods[$method]) { + $packages[$package].Classes[$class].Methods[$method] = @{} + } + + if (!$packages[$package].Classes[$class].Methods[$method][$command.Line]) { + $packages[$package].Classes[$class].Methods[$method][$command.Line] = [ordered]@{ number = $command.Line ; hits = 0 } + } + $packages[$package].Classes[$class].Methods[$method][$command.Line].hits += $command.HitCount + } + + $packages = foreach ($packageGroup in $packages.GetEnumerator()) { + $classGroups = $packageGroup.Value.Classes + $classes = foreach ($classGroup in $classGroups.GetEnumerator()) { + $methodGroups = $classGroup.Value.Methods + $methods = foreach ($methodGroup in $methodGroups.GetEnumerator()) { + $lines = ([object[]]$methodGroup.Value.Values) | New-LineNode + $coveredLines = foreach ($line in $lines) { if (0 -lt $line.attributes.hits) { $line } } + + $method = [ordered]@{ + name = 'method' + attributes = [ordered]@{ + name = $methodGroup.Name + signature = '()' + } + children = [ordered]@{ + lines = $lines | & $SafeCommands["Sort-Object"] { [int]$_.attributes.number } + } + totalLines = $lines.Length + coveredLines = $coveredLines.Length + } + + $method + } + + $lines = ([object[]]$classGroup.Value.Lines.Values) | New-LineNode + $coveredLines = foreach ($line in $lines) { if (0 -lt $line.attributes.hits) { $line } } + + $lineRate = Get-LineRate -CoveredLines $coveredLines.Length -TotalLines $lines.Length + $filename = $classGroup.Name.Substring($commonRoot.Length).Replace('\', '/').TrimStart('/') + + $class = [ordered]@{ + name = 'class' + attributes = [ordered]@{ + name = (& $SafeCommands["Split-Path"] $classGroup.Name -Leaf) + filename = $filename + 'line-rate' = $lineRate + 'branch-rate' = 1 + } + children = [ordered]@{ + methods = $methods | & $SafeCommands["Sort-Object"] { $_.attributes.name } + lines = $lines | & $SafeCommands["Sort-Object"] { [int]$_.attributes.number } + } + totalLines = $lines.Length + coveredLines = $coveredLines.Length + } + + $class + } + + $totalLines = ($classes.totalLines | & $SafeCommands["Measure-Object"] -Sum).Sum + $coveredLines = ($classes.coveredLines | & $SafeCommands["Measure-Object"] -Sum).Sum + $lineRate = Get-LineRate -CoveredLines $coveredLines -TotalLines $totalLines + $packageName = $packageGroup.Name.Substring($commonRoot.Length).Replace('\', '/').TrimStart('/') + + $package = [ordered]@{ + name = 'package' + attributes = [ordered]@{ + name = $packageName + 'line-rate' = $lineRate + 'branch-rate' = 0 + } + children = [ordered]@{ + classes = $classes | & $SafeCommands["Sort-Object"] { $_.attributes.name } + } + totalLines = $totalLines + coveredLines = $coveredLines + } + + $package + } + + $totalLines = ($packages.totalLines | & $SafeCommands["Measure-Object"] -Sum).Sum + $coveredLines = ($packages.coveredLines | & $SafeCommands["Measure-Object"] -Sum).Sum + $lineRate = Get-LineRate -CoveredLines $coveredLines -TotalLines $totalLines + + $coverage = [ordered]@{ + name = 'coverage' + attributes = [ordered]@{ + 'lines-valid' = $totalLines + 'lines-covered' = $coveredLines + 'line-rate' = $lineRate + 'branches-valid' = 0 + 'branches-covered' = 0 + 'branch-rate' = 1 + timestamp = $startTime + version = 0.1 + } + children = [ordered]@{ + sources = [ordered]@{ + name = 'source' + value = $commonRoot.Replace('\', '/') + } + packages = $packages | & $SafeCommands["Sort-Object"] { $_.attributes.name } + } + } + + $xmlDeclaration = '' + $docType = '' + $coverageXml = ConvertTo-XmlElement -Node $coverage + $document = "$xmlDeclaration`n$docType`n$($coverageXml.OuterXml)" + + $document +} + +function New-LineNode { + param( + [parameter(Mandatory = $true, ValueFromPipeline = $true)] [object] $LineObject + ) + + process { + [ordered]@{ + name = 'line' + attributes = $LineObject + } + } +} + +function Get-LineRate { + param( + [parameter(Mandatory = $true)] [int] $CoveredLines, + [parameter(Mandatory = $true)] [int] $TotalLines + ) + + [double]$denominator = if ($TotalLines) { $TotalLines } else { 1 } + + $CoveredLines / $denominator +} + +function ConvertTo-XmlElement { + param( + [parameter(Mandatory = $true)] [object] $Node + ) + + $element = ([xml]"<$($Node.name)/>").DocumentElement + if ($node.attributes) { + $attributes = $node.attributes + foreach ($attr in $attributes.GetEnumerator()) { + $element.SetAttribute($attr.Name, $attr.Value) + } + } + if ($node.children) { + $children = $node.children + foreach ($child in $children.GetEnumerator()) { + $childElement = ([xml]"<$($child.Name)/>").DocumentElement + foreach ($value in $child.Value) { + $childXml = ConvertTo-XmlElement $value + $importedChildXml = $childElement.OwnerDocument.ImportNode($childXml, $true) + $null = $childElement.AppendChild($importedChildXml) + } + $importedChild = $element.OwnerDocument.ImportNode($childElement, $true) + $null = $element.AppendChild($importedChild) + } + } + if ($node.value) { + $element.InnerText = $node.value + } + + $element +} + function Add-XmlElement { param ( [parameter(Mandatory = $true)] [System.Xml.XmlNode] $Parent, @@ -1036,14 +1265,23 @@ function Add-XmlElement { ) $element = $Parent.AppendChild($Parent.OwnerDocument.CreateElement($Name)) if ($Attributes) { - foreach ($key in $Attributes.Keys) { - $attribute = $element.Attributes.Append($Parent.OwnerDocument.CreateAttribute($key)) - $attribute.Value = $Attributes.$key - } + Add-XmlAttribute -Element $element -Attributes $Attributes } return $element } +function Add-XmlAttribute { + param( + [parameter(Mandatory = $true)] [System.Xml.XmlNode] $Element, + [parameter(Mandatory = $true)] [System.Collections.IDictionary] $Attributes + ) + + foreach ($key in $Attributes.Keys) { + $attribute = $Element.Attributes.Append($Element.OwnerDocument.CreateAttribute($key)) + $attribute.Value = $Attributes.$key + } +} + function Add-JaCoCoCounter { param ( [parameter(Mandatory = $true)] [ValidateSet('Instruction', 'Line', 'Method', 'Class')] [string] $Type, diff --git a/src/schemas/Cobertura/coverage-loose.dtd b/src/schemas/Cobertura/coverage-loose.dtd new file mode 100644 index 000000000..35c8272d2 --- /dev/null +++ b/src/schemas/Cobertura/coverage-loose.dtd @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tst/functions/Coverage.Tests.ps1 b/tst/functions/Coverage.Tests.ps1 index 3a41303a6..3fffafa32 100644 --- a/tst/functions/Coverage.Tests.ps1 +++ b/tst/functions/Coverage.Tests.ps1 @@ -52,9 +52,16 @@ InPesterModuleScope { if ($PSVersionTable.PSVersion.Major -ge 5) { Add-Content -Path $testScriptPath -Value @' - class MyClass + class MyBaseClass { + MyBaseClass() + { + 'I am the constructor of base class.' + } + } + + class MyClass : MyBaseClass { - MyClass() + MyClass() : base() { 'I am the constructor.' } @@ -79,11 +86,18 @@ InPesterModuleScope { # Before that, let's just create equivalent commands to above class with exact same line numbers Add-Content -Path $testScriptPath -Value @' + #class MyBaseClass { + function MyBaseClass + { + 'I am the constructor of base class.' + } + #} + #class MyClass #{ function MyClass { - 'I am the constructor.' + MyBaseClass # calls the base constructor } function MethodOne @@ -131,7 +145,9 @@ InPesterModuleScope { # Path deliberately duplicated to make sure the code doesn't produce multiple breakpoints for the same commands $breakpoints = Enter-CoverageAnalysis -CodeCoverage $testScriptPath, $testScriptPath, $testScript2Path, $testScript3Path -UseBreakpoints $UseBreakpoints - @($breakpoints).Count | Should -Be 18 -Because 'it has the proper number of breakpoints defined' + # Output breakpoints so we can compare between PS Versions, when we have a failure on older systems. + Write-Host "Before All: Defined breakpoints (using profiler based code coverage: $(-not $UseBreakpoints)):`n$($breakpoints | Format-Table Class, Function, StartLine, StartColumn, Ast | Out-String)" + @($breakpoints).Count | Should -Be 19 -Because 'it has the proper number of breakpoints defined."' $sb = { $null = & $testScriptPath @@ -153,11 +169,11 @@ InPesterModuleScope { } It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 15 + $coverageReport.NumberOfCommandsExecuted | Should -Be 16 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 18 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 19 } It 'Reports the proper number of analyzed files' { @@ -175,7 +191,7 @@ InPesterModuleScope { } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 15 + $coverageReport.HitCommands.Count | Should -Be 16 } It 'Reports the correct hit command' { @@ -186,7 +202,8 @@ InPesterModuleScope { $coverageReport.HitCommands[0].Class | Should -BeNullOrEmpty # Classes have been introduced in PowerShell 5.0 if ($PSVersionTable.PSVersion.Major -ge 5) { - $coverageReport.HitCommands[9].Class | Should -Be 'MyClass' + $coverageReport.HitCommands[9].Class | Should -Be 'MyBaseClass' + $coverageReport.HitCommands[10].Class | Should -Be 'MyClass' $coverageReport.MissedCommands[2].Class | Should -Be 'MyClass' } else { @@ -198,7 +215,8 @@ InPesterModuleScope { It 'Reports the correct function names' { $coverageReport.HitCommands[0].Function | Should -Be 'NestedFunction' $coverageReport.HitCommands[2].Function | Should -Be 'FunctionOne' - $coverageReport.HitCommands[9].Function | Should -Be 'MyClass' + $coverageReport.HitCommands[9].Function | Should -Be 'MyBaseClass' + $coverageReport.HitCommands[10].Function | Should -Be 'MyClass' $coverageReport.MissedCommands[2].Function | Should -Be 'MethodTwo' } @@ -237,24 +255,29 @@ InPesterModuleScope { - + - + - + + + + + + - - - + + + @@ -278,14 +301,15 @@ InPesterModuleScope { - - - - - - - - + + + + + + + + + @@ -295,13 +319,14 @@ InPesterModuleScope { - - - + + + - + @@ -324,9 +349,9 @@ InPesterModuleScope { - - - + + + ') @@ -370,24 +395,29 @@ InPesterModuleScope { - + - + - + + + + + + - - - + + + @@ -411,14 +441,15 @@ InPesterModuleScope { - - - - - - - - + + + + + + + + + @@ -428,9 +459,9 @@ InPesterModuleScope { - - - + + + @@ -457,14 +488,118 @@ InPesterModuleScope { - - - + + + ') } + It 'Cobertura report must be correct' { + [String]$coberturaReportXml = Get-CoberturaReportXml -TotalMilliseconds 10000 -CoverageReport $coverageReport + $coberturaReportXml = $coberturaReportXml -replace 'timestamp="[0-9]*"', 'timestamp=""' + $coberturaReportXml = $coberturaReportXml -replace "$([System.Environment]::NewLine)", '' + $coberturaReportXml = $coberturaReportXml.Replace($root, 'CommonRoot') + $coberturaReportXml = $coberturaReportXml.Replace($root.Replace('\', '/'), 'CommonRoot') + (Clear-WhiteSpace $coberturaReportXml) | Should -Be (Clear-WhiteSpace ' + + + + + CommonRoot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ') + } + It 'JaCoCo returns empty string when there are 0 analyzed commands' { $coverageReport = [PSCustomObject] @{ NumberOfCommandsAnalyzed = 0 } [String]$jaCoCoReportXml = Get-JaCoCoReportXml -CommandCoverage @{} -TotalMilliseconds 10000 -CoverageReport $coverageReport -Format "CoverageGutters" @@ -472,6 +607,13 @@ InPesterModuleScope { $jaCoCoReportXml | Should -Be ([String]::Empty) } + It 'Cobertura returns empty string when there are 0 analyzed commands' { + $coverageReport = [PSCustomObject] @{ NumberOfCommandsAnalyzed = 0 } + [String]$coberturaReportXml = Get-CoberturaReportXml -CoverageReport $coverageReport -TotalMilliseconds 10000 + $coberturaReportXml | Should -Not -Be $null + $coberturaReportXml | Should -Be ([String]::Empty) + } + It 'Reports the right line numbers' { $coverageReport.HitCommands[$coverageReport.NumberOfCommandsExecuted - 1].Line | Should -Be 1 $coverageReport.HitCommands[$coverageReport.NumberOfCommandsExecuted - 1].StartLine | Should -Be 1 @@ -642,7 +784,7 @@ InPesterModuleScope { BeforeAll { $breakpoints = Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath *.ps1)"; Function = '*' } - @($breakpoints).Count | Should -Be 13 -Because 'it has the proper number of breakpoints defined' + @($breakpoints).Count | Should -Be 14 -Because 'it has the proper number of breakpoints defined' if ($UseBreakpoints) { & $testScriptPath @@ -657,11 +799,11 @@ InPesterModuleScope { } It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 10 + $coverageReport.NumberOfCommandsExecuted | Should -Be 11 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 13 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 14 } It 'Reports the proper number of analyzed files' { @@ -678,7 +820,7 @@ InPesterModuleScope { } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 10 + $coverageReport.HitCommands.Count | Should -Be 11 } It 'Reports the correct hit command' { @@ -747,7 +889,7 @@ InPesterModuleScope { $breakpoints = Enter-CoverageAnalysis -CodeCoverage @{Path = $testScriptPath; Class = '*' } - @($breakpoints).Count | Should -Be 3 -Because 'it has the proper number of breakpoints defined' + @($breakpoints).Count | Should -Be 4 -Because 'it has the proper number of breakpoints defined' if ($UseBreakpoints) { & $testScriptPath @@ -762,11 +904,11 @@ InPesterModuleScope { } It 'Reports the proper number of executed commands' { - $coverageReport.NumberOfCommandsExecuted | Should -Be 2 + $coverageReport.NumberOfCommandsExecuted | Should -Be 3 } It 'Reports the proper number of analyzed commands' { - $coverageReport.NumberOfCommandsAnalyzed | Should -Be 3 + $coverageReport.NumberOfCommandsAnalyzed | Should -Be 4 } It 'Reports the proper number of missed commands' { @@ -774,7 +916,7 @@ InPesterModuleScope { } It 'Reports the proper number of hit commands' { - $coverageReport.HitCommands.Count | Should -Be 2 + $coverageReport.HitCommands.Count | Should -Be 3 } AfterAll {