diff --git a/src/Pester.Runtime.ps1 b/src/Pester.Runtime.ps1 index 72b4914d6..b9da7238f 100644 --- a/src/Pester.Runtime.ps1 +++ b/src/Pester.Runtime.ps1 @@ -2061,6 +2061,7 @@ function PostProcess-DiscoveredBlock { } $blockShouldRun = $false + $allTestsSkipped = $true if ($tests.Count -gt 0) { foreach ($t in $tests) { $t.Block = $b @@ -2140,11 +2141,19 @@ function PostProcess-DiscoveredBlock { $testsToRun[-1].Last = $true $blockShouldRun = $true } + + foreach ($t in $testsToRun) { + if (-not $t.Skip) { + $allTestsSkipped = $false + break + } + } } } $childBlocks = $b.Blocks $anyChildBlockShouldRun = $false + $allChildBlockSkipped = $true if ($childBlocks.Count -gt 0) { foreach ($cb in $childBlocks) { $cb.Parent = $b @@ -2159,9 +2168,17 @@ function PostProcess-DiscoveredBlock { $childBlocksToRun[0].First = $true $childBlocksToRun[-1].Last = $true } + + foreach ($cb in $childBlocksToRun) { + if (-not $cb.Skip) { + $allChildBlockSkipped = $false + break + } + } } $shouldRunBasedOnChildren = $blockShouldRun -or $anyChildBlockShouldRun + $shouldSkipBasedOnChildren = $allTestsSkipped -and $allChildBlockSkipped if ($b.ShouldRun -and -not $shouldRunBasedOnChildren) { if ($PesterPreference.Debug.WriteDebugMessages.Value) { @@ -2170,6 +2187,22 @@ function PostProcess-DiscoveredBlock { } $b.ShouldRun = $shouldRunBasedOnChildren + + if (-not $b.Skip -and $shouldSkipBasedOnChildren) { + if ($PesterPreference.Debug.WriteDebugMessages.Value) { + if ($b.IsRoot) { + Write-PesterDebugMessage -Scope Skip "($($b.BlockContainer)) Container will be skipped because all children are excluded or skipped." + } else { + Write-PesterDebugMessage -Scope Skip "($($b.Path -join '.')) Block will be skipped because all children are excluded or skipped." + } + } + $b.Skip = $true + } elseif ($b.Skip -and -not $shouldSkipBasedOnChildren) { + if ($PesterPreference.Debug.WriteDebugMessages.Value) { + Write-PesterDebugMessage -Scope Skip "($($b.Path -join '.')) Block was marked as Skip, but one or more children should run and is not skipped, so the block will not be skipped." + } + $b.Skip = $false + } } } diff --git a/tst/Pester.Runtime.ts.ps1 b/tst/Pester.Runtime.ts.ps1 index 007744ee2..ca0ec42a6 100644 --- a/tst/Pester.Runtime.ts.ps1 +++ b/tst/Pester.Runtime.ts.ps1 @@ -1229,52 +1229,48 @@ i -PassThru:$PassThru { $container.EachTestTeardown | Verify-Equal 0 } - t "skipping all items in a block will skip the parent block" { - # this is not implemented, but is a possible feature - # which could be implemented together with "if any test is explicitly unskipped in child - # then the block should run, this will be needed for running tests explicitly by path I think - # it also should be taken into consideration whether or not adding a lazySkip is a good idea and how it would - # affect implementation of this. Right now skipping the block goes from parent down, and skipping all items in a block - # will not prevent the parent block setups from running - - # $container = @{ - # OneTimeTestSetup = 0 - # OneTimeTestTeardown = 0 - # EachTestSetup = 0 - # EachTestTeardown = 0 - # TestRun = 0 - # } + t 'skipping all items in a block will skip the parent block' { + $container = @{ + OneTimeTestSetup = 0 + OneTimeTestTeardown = 0 + EachTestSetup = 0 + EachTestTeardown = 0 + TestRun = 0 + } + + $actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock { + New-OneTimeTestSetup -ScriptBlock { $container.OneTimeTestSetup++ } + New-OneTimeTestTeardown -ScriptBlock { $container.OneTimeTestTeardown++ } + + New-Block 'parent block' { + # putting this in child block because each test setup is not supported in root block + New-OneTimeTestSetup -ScriptBlock { $container.OneTimeTestSetup++ } + New-OneTimeTestTeardown -ScriptBlock { $container.OneTimeTestTeardown++ } + + New-EachTestSetup -ScriptBlock { $container.EachTestSetup++ } + New-EachTestTeardown -ScriptBlock { $container.EachTestTeardown++ } + + New-Test 'test1' -Skip { + $container.TestRun++ + 'a' + } - # $actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock { - # New-Block "parent block" { - # New-Block "parent block" { - # # putting this in child block because each test setup is not supported in root block - # New-OneTimeTestSetup -ScriptBlock { $container.OneTimeTestSetup++ } - # New-OneTimeTestTeardown -ScriptBlock { $container.OneTimeTestTeardown++ } - - # New-EachTestSetup -ScriptBlock { $container.EachTestSetup++ } - # New-EachTestTeardown -ScriptBlock { $container.EachTestTeardown++ } - - # New-Test "test1" -Skip { - # $container.TestRun++ - # "a" - # } - - # New-Test "test2" -Skip { - # $container.TestRun++ - # "a" - # } - # } - # } - # }) - - # # $actual.Blocks[0].Skip | Verify-True - # $actual.Blocks[0].ErrorRecord.Count | Verify-Equal 0 - # $container.TestRun | Verify-Equal 0 - # $container.OneTimeTestSetup | Verify-Equal 0 - # $container.OneTimeTestTeardown | Verify-Equal 0 - # $container.EachTestSetup | Verify-Equal 0 - # $container.EachTestTeardown | Verify-Equal 0 + New-Test 'test2' -Skip { + $container.TestRun++ + 'a' + } + } + }) + + # Should be marked as Skip by runtime + $actual.Blocks[0].Skip | Verify-True + $actual.Blocks[0].ErrorRecord.Count | Verify-Equal 0 + + $container.TestRun | Verify-Equal 0 + $container.OneTimeTestSetup | Verify-Equal 0 + $container.OneTimeTestTeardown | Verify-Equal 0 + $container.EachTestSetup | Verify-Equal 0 + $container.EachTestTeardown | Verify-Equal 0 } }