Proper method to handle nested loops? #2175
-
I am running into some issues with my migration from v4 to v5 around usage of -ForEach. One specific scenario is around validation of cmdlet parameters. My top level -ForEach seems to be working as expected but my nested -ForEach neither expands the BeforeDiscovery {
$Cmdlets = Get-Command -Module $env:BHProjectName -CommandType 'Cmdlet', 'Function' -ErrorAction 'Stop'
}
Describe 'Help for <_>' -ForEach $Cmdlets {
BeforeAll {
$Common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'Confirm', 'Whatif'
}
BeforeEach {
$Command = Get-Command $_
$CommandParameters = $Command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object { $_.Name -notin $Common } | Select-Object Name
$CommandParameterNames = $CommandParameters.Name
$Help = Get-Help $Command -ErrorAction SilentlyContinue
$HelpParameters = $Help.Parameters.Parameter | Where-Object { $_.Name -notin $Common } | Sort-Object -Property Name -Unique
}
# If help is not found, synopsis in auto-generated help is the syntax diagram
It 'Should not be auto-generated' {
$Help.Synopsis | Should -Not -Contain 'CommonParameters'
}
# Should be a description for every function
It 'Should have a description' {
$Help.Description | Should -Not -BeNullOrEmpty
}
# Should be at least one example
It 'Should have at least one example' {
($Help.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty
}
# Should be a description for every parameter
It 'Should have description for parameter: <_>' -ForEach $CommandParameterNames {
$CommandParameterName = $_
$ParameterHelp = $HelpParameters | Where-Object { $_.Name -ieq $CommandParameterName }
$ParameterHelp.Description.Text | Should -Not -BeNullOrEmpty
}
} Error [-] Should have description for parameter: <_> 23ms (19ms|4ms)
CommandNotFoundException: The term 'PatchName' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at <ScriptBlock>, /MCS/Tests/Common/Help.Tests.ps1:15
[-] Should have description for parameter: <_> 25ms (18ms|7ms)
CommandNotFoundException: The term 'PatchVersion' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at <ScriptBlock>, /MCS/Tests/Common/Help.Tests.ps1:15
[-] Should have description for parameter: <_> 25ms (21ms|4ms)
CommandNotFoundException: The term 'ProductName' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at <ScriptBlock>, /MCS/Tests/Common/Help.Tests.ps1:15 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I'd also recommend to get function help once per command (Describe) only by using BeforeDiscovery {
$Cmdlets = Get-Command -Name Get-Item
}
Describe 'Help for <_>' -ForEach $Cmdlets {
BeforeDiscovery {
$Common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'Confirm', 'Whatif'
$Command = $_ # Get current from -ForEach $Cmdlets in discovery-phase
$CommandParameters = $Command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object { $_.Name -notin $Common } | Select-Object Name
$CommandParameterNames = $CommandParameters.Name
}
BeforeAll {
# $Common defined in BeforeDiscovery is not available in run-phase. Would have to pass it using `-Foreach` in a outer Describe to reuse.
$Common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'Confirm', 'Whatif'
$Command = $_ # Get current from -ForEach $Cmdlets in run-phase
$Help = Get-Help $_ -ErrorAction SilentlyContinue
$HelpParameters = $Help.Parameters.Parameter | Where-Object { $_.Name -notin $Common } | Sort-Object -Property Name -Unique
}
# Should be a description for every parameter
It 'Should have description for parameter: <_>' -ForEach $CommandParameterNames {
$CommandParameterName = $_
$ParameterHelp = $HelpParameters | Where-Object { $_.Name -ieq $CommandParameterName }
$ParameterHelp.Description.Text | Should -Not -BeNullOrEmpty
}
} |
Beta Was this translation helpful? Give feedback.
-ForEach/TestCases
are evaluated during discovery, so you need to define the parameter-list inBeforeDiscovery
. Related #1684I'd also recommend to get function help once per command (Describe) only by using
BeforeAll
.BeforeEach
runs before every test. Try: