Skip to content

Commit

Permalink
Initialize state in Invoke-Pester and inherit it to children (pester#…
Browse files Browse the repository at this point in the history
…1869)

* Initialize state in Invoke-Pester rather than use global one to allow running Pester in Pester.
  • Loading branch information
nohwnd authored Mar 8, 2021
1 parent eaf8626 commit 50edf2f
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 69 deletions.
92 changes: 41 additions & 51 deletions src/Pester.Runtime.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,35 @@ else {
$PesterPreference = [PesterConfiguration] $PesterPreference
}

$state = [PSCustomObject] @{
# indicate whether or not we are currently
# running in discovery mode se we can change
# behavior of the commands appropriately
Discovery = $false

CurrentBlock = $null
CurrentTest = $null

Plugin = $null
PluginConfiguration = $null
PluginData = $null
Configuration = $null

TotalStopWatch = $null
UserCodeStopWatch = $null
FrameworkStopWatch = $null
Stack = [Collections.Stack]@()
}
function New-PesterState {
$o = [PSCustomObject] @{
# indicate whether or not we are currently
# running in discovery mode se we can change
# behavior of the commands appropriately
Discovery = $false

function Reset-TestSuiteState {
# resets the module state to the default
if ($PesterPreference.Debug.WriteDebugMessages.Value) {
Write-PesterDebugMessage -Scope Runtime "Resetting all state to default."
CurrentBlock = $null
CurrentTest = $null

Plugin = $null
PluginConfiguration = $null
PluginData = $null
Configuration = $null

TotalStopWatch = [Diagnostics.Stopwatch]::StartNew()
UserCodeStopWatch = [Diagnostics.Stopwatch]::StartNew()
FrameworkStopWatch = [Diagnostics.Stopwatch]::StartNew()

Stack = [Collections.Stack]@()
}
$state.Discovery = $false

$state.Plugin = $null
$state.PluginConfiguration = $null
$state.PluginData = $null
$state.Configuration = $null
$o.TotalStopWatch.Restart()
$o.FrameworkStopWatch.Restart()
# user code stopwatch should not be running
# because we are not in user code
$o.UserCodeStopWatch.Reset()

$state.CurrentBlock = $null
$state.CurrentTest = $null
$state.Stack.Clear()
Reset-TestSuiteTimer
return $o
}

function Reset-PerContainerState {
Expand Down Expand Up @@ -80,6 +73,14 @@ function Find-Test {
if ($PesterPreference.Debug.WriteDebugMessages.Value) {
Write-PesterDebugMessage -Scope DiscoveryCore "Running just discovery."
}

# define the state if we don't have it yet, this will happen when we call this function directly
# but normally the parent invoker (most often Invoke-Pester) will set the state. So we don't want to reset
# it here.
if (notDefined state) {
$state = New-PesterState
}

$found = Discover-Test -BlockContainer $BlockContainer -Filter $Filter -SessionState $SessionState

foreach ($f in $found) {
Expand Down Expand Up @@ -1575,22 +1576,8 @@ function Invoke-ScriptBlock {
return $r
}

function Reset-TestSuiteTimer {
if ($null -eq $state.TotalStopWatch) {
$state.TotalStopWatch = [Diagnostics.Stopwatch]::StartNew()
}

if ($null -eq $state.UserCodeStopWatch) {
$state.UserCodeStopWatch = [Diagnostics.Stopwatch]::StartNew()
}

if ($null -eq $state.FrameworkStopWatch) {
$state.FrameworkStopWatch = [Diagnostics.Stopwatch]::StartNew()
}
function Reset-TestSuiteTimer ($o) {

$state.TotalStopWatch.Restart()
$state.FrameworkStopWatch.Restart()
$state.UserCodeStopWatch.Reset()
}

function Switch-Timer {
Expand Down Expand Up @@ -1842,6 +1829,12 @@ function Invoke-Test {
# set the incoming value for all the child scopes
# TODO: revisit this because this will probably act weird as we jump between session states
$PesterPreference = $Configuration
# define the state if we don't have it yet, this will happen when we call this function directly
# but normally the parent invoker (most often Invoke-Pester) will set the state. So we don't want to reset
# it here.
if (notDefined state) {
$state = New-PesterState
}

$state.Plugin = $Plugin
$state.PluginConfiguration = $PluginConfiguration
Expand Down Expand Up @@ -2560,13 +2553,10 @@ function ConvertTo-HumanTime {
}
}

# initialize internal state
Reset-TestSuiteState

# if -not build
& $SafeCommands['Export-ModuleMember'] -Function @(
# the core stuff I am mostly sure about
'Reset-TestSuiteState'
'New-PesterState'
'New-Block'
'New-ParametrizedBlock'
'New-Test'
Expand Down
5 changes: 5 additions & 0 deletions src/Pester.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,11 @@ function Invoke-Pester {
# this will inherit to child scopes and allow Describe / Context to run directly from a file or command line
$invokedViaInvokePester = $true

# this will inherit to child scopes and allow Pester to run in Pester, not checking if this is
# already defined because we want a clean state for this Invoke-Pester even if it runs inside another
# testrun (which calls Invoke-Pester itself)
$state = New-PesterState

# TODO: Remove all references to mock table, there should not be many.
$script:mockTable = @{}
# todo: move mock cleanup to BeforeAllBlockContainer when there is any
Expand Down
24 changes: 24 additions & 0 deletions tst/Pester.RSpec.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1426,4 +1426,28 @@ i -PassThru:$PassThru {
$test.ErrorRecord[0] -like "*Legacy Should syntax (without dashes) is not supported in Pester 5.*"
}
}

b "Running Pester in Pester" {
t "Invoke-Pester can run in Invoke-Pester" {
$container = New-PesterContainer -ScriptBlock {
Describe "Run Pester in Pester" {
It "Runs the test" {
$c = New-PesterContainer -ScriptBlock {
Describe "d" {
It "i" {
1 | Should -Be 1
}
}
}

$r = Invoke-Pester -Container $c -PassThru
$r.TotalCount | Should -Be 1
}
}
}

$result = Invoke-Pester -Container $container -PassThru
$result.TotalCount | Should -Be 1
}
}
}
16 changes: 0 additions & 16 deletions tst/Pester.Runtime.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ i -PassThru:$PassThru {

b "Basic" {
t "Given a scriptblock with 1 test in it, it finds 1 test" {
Reset-TestSuiteState
$actual = (Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -158,7 +157,6 @@ i -PassThru:$PassThru {
}

t "Given scriptblock with 2 tests in it it finds 2 tests" {
Reset-TestSuiteState
$actual = (Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -174,14 +172,12 @@ i -PassThru:$PassThru {

b "block" {
t "Given 0 tests it returns block containing no tests" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock { })

$actual.Blocks[0].Tests.Count | Verify-Equal 0
}

t "Given 0 tests it returns block containing 0 tests" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -194,7 +190,6 @@ i -PassThru:$PassThru {

b "Find common setup for each test" {
t "Given block that has test setup for each test it finds it" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-EachTestSetup { setup }
Expand All @@ -208,7 +203,6 @@ i -PassThru:$PassThru {

b "Finding setup for all tests" {
t "Find setup to run before all tests in the block" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-OneTimeTestSetup { oneTimeSetup }
Expand All @@ -222,7 +216,6 @@ i -PassThru:$PassThru {

b "Finding blocks" {
t "Find tests in block that is explicitly specified" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -234,7 +227,6 @@ i -PassThru:$PassThru {
}

t "Find tests in blocks that are next to each other" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -253,7 +245,6 @@ i -PassThru:$PassThru {
}

t "Find tests in blocks that are inside of each other" {
Reset-TestSuiteState
$actual = Find-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { }
Expand All @@ -275,7 +266,6 @@ i -PassThru:$PassThru {

b "Executing tests" {
t "Executes 1 test" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { "a" }
Expand All @@ -289,7 +279,6 @@ i -PassThru:$PassThru {
}

t "Executes 2 tests next to each other" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { "a" }
Expand All @@ -309,7 +298,6 @@ i -PassThru:$PassThru {
}

t "Executes 2 tests in blocks next to each other" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { "a" }
Expand All @@ -333,7 +321,6 @@ i -PassThru:$PassThru {
}

t "Executes 2 tests deeper in blocks" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { "a" }
Expand All @@ -360,7 +347,6 @@ i -PassThru:$PassThru {
$c = @{
Call = 0
}
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer @(
(New-BlockContainerObject -ScriptBlock {
$c.Call++
Expand Down Expand Up @@ -875,7 +861,6 @@ i -PassThru:$PassThru {
}

t "continues to second block even if the first block is excluded" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" -Tag "DoNotRun" {
New-Test "test1" { "a" }
Expand All @@ -894,7 +879,6 @@ i -PassThru:$PassThru {
}

t "continues to second test even if the first test is excluded" {
Reset-TestSuiteState
$actual = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock {
New-Block "block1" {
New-Test "test1" { "a" } -Tag "DoNotRun"
Expand Down
2 changes: 1 addition & 1 deletion tst/functions/It.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Set-StrictMode -Version Latest

# TODO: These tests depend on Pester state that no longer exists, keeping this for future reference, most of it is already tested by P
# TODO: These tests depend on the OLD Pester state that no longer exists, keeping this for future reference, most of it is already tested by P
return


Expand Down
2 changes: 1 addition & 1 deletion tst/functions/PesterState.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# TODO: Pester state no longer exists, keeping this for reference, to see if there are some egde cases worth testing
# TODO: the OLD Pester state no longer exists, keeping this for reference, to see if there are some egde cases worth testing
return
Set-StrictMode -Version Latest

Expand Down

0 comments on commit 50edf2f

Please sign in to comment.