Pester 5 变量范围问题 - BeforeDiscovery/It

Pester 5 variable scoping issue - BeforeDiscovery/It

编辑

问题的症结在于:如何访问 BeforeDiscovery 块中声明的 It 块中未被 [=15= 传递的变量]构造?


我很难适应 Pester 5 中的 Discovery/Run 阶段和变量范围

背景

我们正在移动服务器,我要测试的是

  1. serverA 上的每一股在 serverB 上也 存在
  2. serverA 上的每个 可读 分享在 serverB 上也是 可读

使用 Pester 5,下面的代码按预期运行,但要使其正常工作,我必须检索 $toShares 两次。在我的实际测试中检索共享是使用 net view 并且是一个相当长的 运行 操作。

  1. 我必须在发现阶段检索 $toShares 以构建 $readableFromShares 列表
  2. 我必须在 BeforeAll 块中检索相同的 $toShares 才能在 should exists 测试
  3. 中使用它们

问题

我怎样才能最好地重组我的测试,以便我只需要检索一次 $toShares

测试码

$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
        }
    }
}

输出 包括两次故意失败的测试


编辑

测试用例包括

  1. 两个 from/to 服务器(一个)
  2. 每组服务器的不同共享名

测试

$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
        }
    }
} 

我对 pester 不熟悉,但我有一些建议:

使用 Get-CimInstance 从一个位置列出股票可能会更幸运(或速度)。这是非纠缠代码:

# Discovery
$shares = $ServerNames | Foreach { Get-CimInstance –Class Win32_Share –ComputerName $_ }

# Run
# simple compare of the shares list between servers
$diff = Compare-Object -Property Name `
    -ReferenceObject  ($shares|where PSComputerName -Like $ServerA) `
    -DifferenceObject ($shares|where PSComputerName -Like $ServerB) `

# $diff should -eq $null

要测试它们是否都可读,请使用相同的 $shares 如下所示:

foreach ($share in $shares) {
    It "\$($share.PSComputerName)$($share.Name) should be readable" {
        (Test-Path "\$($share.PSComputerName)$($share.Name)" -ea SilentlyContinue) | 
            Should -Be $True    
    }
}

解决方案是使用您希望在 It 块中可用的任何数据来丰富传递给 -foreach 子句的变量。

在下面的示例中,$fromShares 数组现在包含一个对象数组,而不是一个普通的字符串数组。每个对象仍包含共享名称,还包含您在测试中需要的 $toShares 数组。


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            
        }
    }
}