It took me awhile to get around this logic. The Pester v5 script no longer runs in top down fashion. Unlike Pester v4 or older version, Pester v5 runs in two different phases.
In Descovery phase, it gathers all the infomation about the test script and get it ready for the Run phase. Technically speaking, Discovery phase only executes BeforeDiscovery, Describe, Context and anything else outside the It blocks.
Variables from Discovery are not available at Run stage. This is where you encounter the problem if you are running a test depending on some data sets. If your Pester test defines or captures the data in Descovery phase, You will need to explicitly attach it to Describe, Context or It blocks using -Foreach or -TestCases to make the data available in Run phase.
Pester v5 provides some sort of isolation between the Discovery and Run phases. Run phase will execute the It block. It also executes BeforeAll, BeforeEach, AfterAll, AfterEach blocks which I think are just the surroundings to support the It block execution.
BeforeDiscovery {
Write-Host "1 BeforeDiscovery Outside Describe block"
}
BeforeAll{
Write-Host "2 BeforeAll Outside Describe block"
}
Write-Host "3 Not in any blocks Outside Describe block"
Describe "Pester v5"{
BeforeDiscovery {
Write-Host "4 BeforeDiscovery Inside Describe block"
}
BeforeAll{
Write-Host "5 BeforeAll Inside Describe block"
}
BeforeEach{
Write-Host "6 BeforeEach Inside Describe block"
}
Write-Host "7 Not in any blocks Inside Describe block"
It "Should be true"{
Write-Host "8 It block Within It"
(1 + 1) | Should -Be 2
}
AfterAll{
Write-Host "9 AfterAll Inside Describe block"
}
AfterEach{
Write-Host "10 AfterEach Inside Describe block"
}
}
Invoke-Pester .\Test-Pesterv5.Tests.ps1
If you run the above test with Pester v5, you will see that:
1, 3, 4 and 7 run at Discovery phase and
2, 5, 6, 8, 9 and 10 run at Run phase.
So just be mindful where you put your functions and variables when you write your Pester v5 test. In my opinion, if you are just testing your functions, put all your functions in BeforeAll and call them from your It block. If you are running data driven test, put all your data in BeforeDiscovery and hook them up with Foreach or TestCases between the two phases.
Bridge between Discovery and Run phase:
- -Foreach is simple, you could just use $_ ($PSItem) to loop through the whole collections.
- -TestCases uses the hashtable and Pester v5 creates the variable for each Key in the hashtable to be accessible during the Run phase.
Pester v5 Discovery & Run phases - the glue between the two: -Foreach and -TestCases