diff --git a/src/Pester.RSpec.ps1 b/src/Pester.RSpec.ps1 index e15094b98..10ba6759b 100644 --- a/src/Pester.RSpec.ps1 +++ b/src/Pester.RSpec.ps1 @@ -176,6 +176,9 @@ function PostProcess-RspecTestRun ($TestRun) { $b.Result = if ($b.Skip) { "Skipped" } + elseif (0 -lt $b.ErrorRecord.Count) { + "Failed" + } elseif ($b.Passed) { "Passed" } @@ -206,12 +209,12 @@ function PostProcess-RspecTestRun ($TestRun) { $b.result = if ($b.Skip) { "Skipped" } - elseif ($b.Passed) { - "Passed" - } elseif (0 -lt $b.ErrorRecord.Count) { "Failed" } + elseif ($b.Passed) { + "Passed" + } elseif (-not $discoveryOnly -and $b.ShouldRun -and (-not $b.Executed -or -not $b.Passed)) { "Failed" } diff --git a/tst/Pester.RSpec.ts.ps1 b/tst/Pester.RSpec.ts.ps1 index c8847d604..6cea4cf90 100644 --- a/tst/Pester.RSpec.ts.ps1 +++ b/tst/Pester.RSpec.ts.ps1 @@ -2966,4 +2966,77 @@ i -PassThru:$PassThru { $ex.Exception.Message | Verify-Like '*Unbound scriptblock*' } } + + # Regression test for https://github.com/pester/Pester/issues/2538 + # When discovery of a Describe body throws after at least one passing It, the + # container ends up with Passed=$true (the It passed) AND a non-empty + # ErrorRecord (the discovery throw lands on the container, not the inner + # block). Before this fix the result was computed by checking Passed before + # ErrorRecord, so such a container was reported as Passed even though the run + # also listed it under FailedContainers. The fix flips the precedence so + # ErrorRecord wins. + b "Discovery errors mark container as Failed" { + t "container with discovery error after a passing It has result Failed" { + # Exact repro from the issue: an It runs (so Passed becomes $true) and + # then a throw at the bottom of the Describe body fails discovery. + $sb = { + Describe 'd' { + It '1' {} + throw 'omg' + } + } + + $r = Invoke-Pester -Configuration ([PesterConfiguration]@{ + Run = @{ ScriptBlock = $sb; PassThru = $true } + Output = @{ Verbosity = 'None' } + }) + + $r.Result | Verify-Equal 'Failed' + $r.Containers[0].Result | Verify-Equal 'Failed' + $r.FailedContainersCount | Verify-Equal 1 + } + + t "container with BeforeAll throw has result Failed" { + # BeforeAll throws at execution time. Passed is $false but ErrorRecord + # is set; verify the ErrorRecord branch still produces Failed (it would + # also fall through to the existing ShouldRun/Executed branch, but the + # new ErrorRecord branch is what should fire). + $sb = { + Describe 'Has BeforeAll error' { + BeforeAll { + throw 'deliberate BeforeAll error' + } + It 'should not run' { + $true | Should -Be $true + } + } + } + + $r = Invoke-Pester -Configuration ([PesterConfiguration]@{ + Run = @{ ScriptBlock = $sb; PassThru = $true } + Output = @{ Verbosity = 'None' } + }) + + $r.Result | Verify-Equal 'Failed' + $r.Containers[0].Result | Verify-Equal 'Failed' + } + + t "container without errors still passes" { + $sb = { + Describe 'All good' { + It 'passes' { + $true | Should -Be $true + } + } + } + + $r = Invoke-Pester -Configuration ([PesterConfiguration]@{ + Run = @{ ScriptBlock = $sb; PassThru = $true } + Output = @{ Verbosity = 'None' } + }) + + $r.Result | Verify-Equal 'Passed' + $r.Containers[0].Result | Verify-Equal 'Passed' + } + } }