Edit
The crux of the question is: how do I get access to variable(s) declared in a BeforeDiscovery
block in my It
blocks that are not passed through by the it -foreach $var
construct?
I'm having difficulties adjusting to the Discovery/Run phase and Scoping of Variables in Pester 5
Background
We are moving servers and what I'm trying to test is
serverA
also exists on serverB
.serverA
is also readable on serverB
.Using Pester 5, below code runs as intented but to make it work, I have to retrieve the $toShares
twice. Retrieving the shares in my actual tests is using a net view
and is a fairly long running operaton.
$toShares
in the Discovery phase to construct the $readableFromShares
list$toShares
in a BeforeAll block to have them available in the should exists
testQuestion
How can I best restructure my test so that I only need to retrieve the $toShares
once?
Testcode
$PesterPreference = [PesterConfiguration]::Default
$PesterPreference.Output.Verbosity = 'Detailed'
function Test-Path {$True} # hide the real Test-Path function
Describe "Describe" -ForEach @(
@{fromServer ='serverA'; toServer = 'serverB'}
@{fromServer ='serverC'; toServer = 'serverD'}
){
BeforeDiscovery {
$fromShares = 'share1', 'share2', 'share3'
# $toShares is needed here to construct the readableFromShares array
$toShares = 'share1', 'share2'
$readableFromShares = $fromShares |
Where-Object {$toShares -contains $_} |
Where-Object {Test-Path "\\$($fromServer)\$($_)"}
}
Context "<fromServer> samba shares should exist on <toServer>" {
BeforeAll {
# the "same" $toShares is needed here to be available in the exist tests
$toShares = 'share1', 'share2'
}
It "Does \\<toServer>\<_> exist" -ForEach $fromShares {
$toShares -contains $_ | Should -Be $true
}
}
Context "Readable <fromServer> samba shares should als be readable on <toServer>" {
It "<_> is readable on <fromServer>. \\<toServer>\<_> should also be readable." -ForEach $readableFromShares {
Test-Path "\\$($toServer)\$($_)"| Should -Be $True
}
}
}
Output including two deliberate failing tests
Edit
Testcase including
Test
$PesterPreference = [PesterConfiguration]::Default
$PesterPreference.Output.Verbosity = 'Detailed'
function Test-Path {$True} # hides the real Test-Path
function Get-FromShares($fromServer) {if ($fromServer -eq 'serverA') { @('ABshare1', 'ABshare2', 'ABshare3') } else {@('XYshare1', 'XYshare2', 'XYshare3')}}
function Get-ToShares($toServer) {if ($toServer -eq 'serverB') { @('ABshare1', 'ABshare2') } else {@('XYshare1', 'XYshare2')}}
class Shares { static $toShares = @{} }
function Test-Path {$True} # hides the real Test-Path
Describe "Describe" -ForEach @(
@{fromServer ='serverA'; toServer = 'serverB'}
@{fromServer ='serverX'; toServer = 'serverY'}
){
#It "Define shares" -TestCases @( 1 ) { class Shares { static [string[]]$toShares = @('share1', 'share2') } }
BeforeDiscovery {
$fromShares = Get-FromShares($fromServer)
[Shares]::toShares =@{ $fromServer = Get-ToShares($toServer)}
$toShares = [Shares]::toShares[$fromServer]
$readableFromShares = $fromShares |
Where-Object {$toShares -contains $_} |
Where-Object {Test-Path "\\$($fromServer)\$($_)"}
}
Context "<fromServer> samba shares should exist on <toServer>" {
BeforeAll {
$toShares = [Shares]::toShares[$fromServer]
}
It "Does \\<toServer>\<_> exist" -ForEach $fromShares {
$toShares -contains $_ | Should -Be $true
}
}
Context "Readable <fromServer> samba shares should als be readable on <toServer>" {
It "<_> is readable on <fromServer>. \\<toServer>\<_> should also be readable." -ForEach $readableFromShares {
Test-Path "\\$($toServer)\$($_)"| Should -Be $True
}
}
}
The solution is to enrich the variables passed to the -foreach
clauses with whatever data you like to have available in the It
blocks.
In below example, the $fromShares
array now contains an array of objects instead of a plain array of strings. Each object still contains the share name and also contains the $toShares
array you need in your test.
Describe "Describe" -ForEach @(
@{fromServer ='serverA'; toServer = 'serverB'}
@{fromServer ='serverX'; toServer = 'serverY'}
){
BeforeDiscovery {
$toShares = Get-ToShares($toServer)
$fromShares = Get-FromShares($fromServer) | % {
[PSCustomObject]@{
fromShare = $_
toShares = $toShares
}
}
$readableFromShares = $fromShares |
Where-Object {$toShares -contains $_} |
Where-Object {Test-Path "\\$($fromServer)\$($_)"}
}
Context "<fromServer> samba shares should exist on <toServer>" {
BeforeAll {
$toShares = [Shares]::toShares[$fromServer]
}
It "Does \\<toServer>\<_.fromShare> exist" -ForEach $fromShares {
$_.toShares -contains $_.fromShare | Should -Be $true
}
}
Context "Readable <fromServer> samba shares should als be readable on <toServer>" {
It "<_> is readable on <fromServer>. \\<toServer>\<_> should also be readable." -ForEach $readableFromShares {
Test-Path "\\$($toServer)\$($_)"| Should -Be $True
}
}
}