困扰 5:自动化
Pester 5: Automate It
为了我的爱好项目ConvertTo-Expression
, I am rebuilding my test (Pester 5) script. I would like to automate the It
(and possibly the Context
part) as there are large number of syntax formats to test for and the function actually roundtrips which &([ScriptBlock]::Create("$Expression"))
. For a Minimal, Reproducible Example, I am using ConvertTo-Json
which roundtrips with ConvertTo-Json
。
我对这个问题的目标基本上是创建一个 easy 测试语法相关函数是否正确往返,例如:
Test -Compress '{"a":1}'
我想做这样的事情:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
# BeforeEach {
# $Compress = $True
# $Json = '{"a":1}'
# $Object = ConvertFrom-Json $Json
# }
It $It { ConvertTo-Json -Compress:$Compress -Depth 9 $Object | Should -Be $Json }
}
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
但这会导致如下错误:
Starting discovery in 1 files.
Discovery finished in 35ms.
[-] Syntax check.Compress.{"a":1} 15ms (13ms|2ms)
RuntimeException: The variable '$Compress' cannot be retrieved because it has not been set.
at <ScriptBlock>, C:\Test.ps1:6
Tests completed in 140ms
Tests Passed: 0, Failed: 1, Skipped: 0 NotRun: 0
启用注释掉的硬编码 BeforeEach
returns expcted 结果:
Starting discovery in 1 files.
Discovery finished in 32ms.
[+] C:\Test.ps1 197ms (80ms|88ms)
Tests completed in 202ms
Tests Passed: 1, Failed: 0, Skipped: 0 NotRun: 0
我想把It
(和Context
)放在一个函数中并用参数控制它们,这样我就可以做一个像Test -Compress '{"a":1}'
这样的简单测试。不幸的是,我完全迷失在新的 Pester 发现范围中,并开始怀疑这是否真的可以通过 Pester 5 实现。
我找到了一种使用 -TestCases
参数的方法:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
$TestCase = @{ Params = @{ Compress = $Compress; Object = $Object; Json = $Json } }
It $It -TestCases $TestCase {
param($Params)
ConvertTo-Json -Compress:$Params.Compress -Depth 9 $Params.Object | Should -Be $Params.Json
}
}
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
(但我仍然愿意接受其他建议,尤其是如果我似乎忽略了一些明显的东西)
我认为问题在于感兴趣的变量仅在 嵌套 脚本块(传递给 It
的脚本块)内被引用,而不是外部(一个传递给 Context
).
一个简单的解决方案是在外部脚本块上调用 .GetNewClosure()
方法,它在调用作用域的局部变量周围形成一个闭包:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
It $It { ConvertTo-Json -Compress:$Compress -Depth 9 $Object | Should -Be $Json }
}.GetNewClosure() # This captures $Json, $Compress, $It, and $Object
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
请注意,docs are very terse at the moment, but the conversation in GitHub issue #9077 表明 .GetNewClosure()
返回的脚本块在新创建的 动态(内存中)模块中运行 。
为了我的爱好项目ConvertTo-Expression
, I am rebuilding my test (Pester 5) script. I would like to automate the It
(and possibly the Context
part) as there are large number of syntax formats to test for and the function actually roundtrips which &([ScriptBlock]::Create("$Expression"))
. For a Minimal, Reproducible Example, I am using ConvertTo-Json
which roundtrips with ConvertTo-Json
。
我对这个问题的目标基本上是创建一个 easy 测试语法相关函数是否正确往返,例如:
Test -Compress '{"a":1}'
我想做这样的事情:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
# BeforeEach {
# $Compress = $True
# $Json = '{"a":1}'
# $Object = ConvertFrom-Json $Json
# }
It $It { ConvertTo-Json -Compress:$Compress -Depth 9 $Object | Should -Be $Json }
}
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
但这会导致如下错误:
Starting discovery in 1 files.
Discovery finished in 35ms.
[-] Syntax check.Compress.{"a":1} 15ms (13ms|2ms)
RuntimeException: The variable '$Compress' cannot be retrieved because it has not been set.
at <ScriptBlock>, C:\Test.ps1:6
Tests completed in 140ms
Tests Passed: 0, Failed: 1, Skipped: 0 NotRun: 0
启用注释掉的硬编码 BeforeEach
returns expcted 结果:
Starting discovery in 1 files.
Discovery finished in 32ms.
[+] C:\Test.ps1 197ms (80ms|88ms)
Tests completed in 202ms
Tests Passed: 1, Failed: 0, Skipped: 0 NotRun: 0
我想把It
(和Context
)放在一个函数中并用参数控制它们,这样我就可以做一个像Test -Compress '{"a":1}'
这样的简单测试。不幸的是,我完全迷失在新的 Pester 发现范围中,并开始怀疑这是否真的可以通过 Pester 5 实现。
我找到了一种使用 -TestCases
参数的方法:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
$TestCase = @{ Params = @{ Compress = $Compress; Object = $Object; Json = $Json } }
It $It -TestCases $TestCase {
param($Params)
ConvertTo-Json -Compress:$Params.Compress -Depth 9 $Params.Object | Should -Be $Params.Json
}
}
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
(但我仍然愿意接受其他建议,尤其是如果我似乎忽略了一些明显的东西)
我认为问题在于感兴趣的变量仅在 嵌套 脚本块(传递给 It
的脚本块)内被引用,而不是外部(一个传递给 Context
).
一个简单的解决方案是在外部脚本块上调用 .GetNewClosure()
方法,它在调用作用域的局部变量周围形成一个闭包:
Function Test ([String]$Json, [Switch]$Compress, [String]$It = $Json) {
$Context = if ($Compress) { 'Compress' } Else { 'Default' }
$Object = ConvertFrom-Json $Json
Context $Context {
It $It { ConvertTo-Json -Compress:$Compress -Depth 9 $Object | Should -Be $Json }
}.GetNewClosure() # This captures $Json, $Compress, $It, and $Object
}
Describe 'Syntax check' {
Test -Compress '{"a":1}'
}
请注意,docs are very terse at the moment, but the conversation in GitHub issue #9077 表明 .GetNewClosure()
返回的脚本块在新创建的 动态(内存中)模块中运行 。