简体   繁体   English

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

[英]Pester 5 variable scoping issue - BeforeDiscovery/It

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?问题的症结在于:如何访问It块中未通过it -foreach $var构造传递的BeforeDiscovery块中声明的变量?


I'm having difficulties adjusting to the Discovery/Run phase and Scoping of Variables in Pester 5我很难适应 Pester 5 中的发现/运行阶段和变量范围

Background背景

We are moving servers and what I'm trying to test is我们正在移动服务器,我要测试的是

  1. that every share on serverA also exists on serverB . serverB上的每个共享也存在serverA上。
  2. that every readable share on serverA is also readable on serverB . serverB上的每个可读共享在serverA上也是可读的。

Using Pester 5, below code runs as intented but to make it work, I have to retrieve the $toShares twice.使用 Pester 5,下面的代码按预期运行,但要使其正常工作,我必须检索$toShares两次。 Retrieving the shares in my actual tests is using a net view and is a fairly long running operaton.在我的实际测试中检索共享是使用net view ,并且是一个相当长的运行操作。

  1. I have to retrieve $toShares in the Discovery phase to construct the $readableFromShares list我必须在 Discovery 阶段检索$toShares以构建$readableFromShares列表
  2. I have to retrieve an identical $toShares in a BeforeAll block to have them available in the should exists test我必须在 BeforeAll 块中检索相同的$toShares才能使它们在should exists的测试中可用

Question问题

How can I best restructure my test so that I only need to retrieve the $toShares once?我怎样才能最好地重组我的测试,以便我只需要检索一次$toShares

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 Output包括两个故意失败的测试

输出测试用例


Edit编辑

Testcase including测试用例包括

  1. Two from/to servers (io one)两个从/到服务器(io 一个)
  2. Different sharenames for each set of servers每组服务器的不同共享名

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

In below example, the $fromShares array now contains an array of objects instead of a plain array of strings.在下面的示例中, $fromShares数组现在包含一个对象数组,而不是一个普通的字符串数组。 Each object still contains the share name and also contains the $toShares array you need in your test.每个 object 仍然包含共享名称,还包含您在测试中需要的$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            
        }
    }
} 

I'm not familiar with pester, but I do have some suggestions:我不熟悉纠缠,但我确实有一些建议:

You may have better luck (or speed) using Get-CimInstance to list the shares from one location.您可能有更好的运气(或速度)使用Get-CimInstance从一个位置列出共享。 Here's non-pester code for that:这是非纠缠代码:

# 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

And to test if they're all readable, use the same $shares something like this:并测试它们是否都可读,使用相同的$shares像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM