Pester 5嵌套循环中如何访问多个变量?
Pester V4 迁移到 V5:嵌套
-ForEach 循环的变量访问解决方案 问题背景
将Pester测试从V4版本迁移到V5版本时,按照最佳实践将传统foreach()循环替换为Describe -ForEach{}语法,用于检查模块中每个函数的注释式帮助是否完整。V4中数组变量可以在所有Describe/Context/It块中直接访问,但V5要求初始化代码必须放在BeforeDiscovery块中,且子块无法自动继承父块BeforeDiscovery中的变量。当前卡在最后一个-ForEach循环:无法同时访问来自BeforeDiscovery块的$parameterNames和父循环的$helpParameterNames。
V4 原始代码
$commands = Get-Command -Module ModuleName foreach ($command in $commands) { $commandName = $command.Name $help = Get-Help $commandName -ErrorAction SilentlyContinue Describe "Test help for $commandName" -Tag Help { <It Tests Removed> Context "Test parameter help for $commandName" { $common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable' $parameters = $command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object Name -notin $common $parameterNames = $parameters.Name $helpParameterNames = $help.Parameters.Parameter.Name | Sort-Object -Unique foreach ($parameter in $parameters) { $parameterName = $parameter.Name $parameterHelp = $help.parameters.parameter | Where-Object Name -EQ $parameterName <It Tests Removed> } foreach ($helpParm in $helpParameterNames) { It "Should find parameter $helpParm in the function" { $helpParm -in $parameterNames | Should Be $true } } } } }
V5 迁移中的问题代码
BeforeDiscovery { $commands = Get-Command -Module ModuleName } Describe "Help Rules" -Tags Build, Help -ForEach $commands { BeforeDiscovery { $commandName = $_.Name $common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable' $parameters = (Get-Command $commandName).ParameterSets.Parameters | Where-Object -Property Name -NotIn $common | Sort-Object -Property Name -Unique $parameterNames = $parameters.Name $help = Get-Help $commandName -Full -ErrorAction SilentlyContinue } Context "General Rules for $commandName" -ForEach @{help = $help} { <It Tests Removed> Describe "Parameter Rules for <parameter.Name>" -Tags Help, Parameter -ForEach $parameters { BeforeAll { $parameter = $_.parameters # 此处错误,应直接取 $_ $helpParameterNames = $help.Parameters.Parameter.Name | Sort-Object -Unique $parameterHelp = $help.parameters.parameter | Where-Object Name -EQ $parameter.Name } <It Tests Removed> } It "Should find parameter <helpParameter> in the function" -Tag Help, Parameter -ForEach $helpParameterNames { BeforeAll { $helpParameter = $_ } $helpParameter -in $parameterNames | Should -BeTrue # 此处无法访问 $parameterNames } } }
解决方法
V5的Discovery阶段(BeforeDiscovery、Describe/Context/It的定义)和Run阶段(测试执行)是完全分离的,BeforeDiscovery中的变量不会自动传递到Run阶段。解决核心是:在Discovery阶段将需要的变量打包成自定义对象数组,通过-ForEach传递给子块,确保迭代时能同时拿到所有必要数据。
修改后的完整V5代码
BeforeDiscovery { $commands = Get-Command -Module ModuleName } Describe "Help Rules" -Tags Build, Help -ForEach $commands { BeforeDiscovery { $commandName = $_.Name $common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable' $parameters = (Get-Command $commandName).ParameterSets.Parameters | Where-Object -Property Name -NotIn $common | Sort-Object -Property Name -Unique $parameterNames = $parameters.Name $help = Get-Help $commandName -Full -ErrorAction SilentlyContinue # 打包参数验证所需的两个变量为对象数组 $helpParamValidationSet = $help.Parameters.Parameter.Name | Sort-Object -Unique | ForEach-Object { [PSCustomObject]@{ HelpParameter = $_ ExpectedParameterNames = $parameterNames } } } Context "General Rules for $commandName" -ForEach @{help = $help; parameters = $parameters} { <It Tests Removed> Describe "Parameter Rules for <parameter.Name>" -Tags Help, Parameter -ForEach $parameters { BeforeAll { $parameter = $_ # 修正:直接取当前迭代的parameter对象 $parameterHelp = $help.parameters.parameter | Where-Object Name -EQ $parameter.Name } <It Tests Removed> } # 使用打包后的对象数组进行循环,同时拿到两个变量 It "Should find parameter <HelpParameter> in the function" -Tag Help, Parameter -ForEach $helpParamValidationSet { $_.HelpParameter -in $_.ExpectedParameterNames | Should -BeTrue } } }
关键修改点说明
- 变量打包传递:在
Describe的BeforeDiscovery中,将$helpParameterNames和$parameterNames组合成[PSCustomObject]数组$helpParamValidationSet,确保It循环时能同时访问两个变量。 - 修正迭代变量取值:在
Describe "Parameter Rules for <parameter.Name>"的BeforeAll中,将$parameter = $_.parameters改为$parameter = $_,因为-ForEach $parameters的每个迭代项就是单个参数对象。 - 移除冗余
BeforeAll:It块中无需额外定义BeforeAll,直接通过$_访问迭代对象的属性即可。
内容的提问来源于stack exchange,提问作者Ninja
相关产品推荐
相关产品推荐

