Powershell 中的同步单元测试执行
Synchronous unit test execution in Powershell
我有一个 Pester It 块,如下所示:
It "should add a header" {
{
$DifferenceObject = Get-Content -Path $PathToFile1
Set-PowershellFile -Path $PathToFile2
$ReferencedObject = Get-Content -Path $PathToFile2
Compare-Object -ReferenceObject $ReferencedObject -DifferenceObject $DifferenceObject | should -be $null
}
}
Set-PowershellFile 只是用一些新文本更新文件。我认为上面的代码会执行以下操作,但我只想确认:
- 它获取位于 'PathToFile1'
的文件的内容
- 它使用 Set-PowershellFile 将文件设置为 'PathToFile2',然后获取该文件的新内容。
- 将新更新的文件与第一个文件的内容进行比较,确保它们相同。
这是正确的吗?当我 运行 我的单元测试时,在 Set-PowershellFile 中所做的文件更改不会持续存在,但单元测试通过了。我假设将此代码包装在 {} 中的 if 块内会导致同步行为,但不会 'commit' 文件更改。这些都正确吗?
Mathias R. Jessen 在评论中提供了关键指针 - 只需 省略 内部 {
和 }
- 但由于我之前已经看到了潜在的误解,因此值得深入挖掘:
虽然 { ... }
块是大多数 PowerShell 语句的常规部分,例如 foreach
和 if
, 孤立地 它们 不提供一个范围内的语句块立即执行,例如它在C#中的工作方式。
相反,{ ... }
隔离 是 PowerShell script block, i.e. a block of statements for later execution, on demand, either via &
, the call operator, for execution in a child scope of, or via .
, the dot-sourcing operator 的字面形式,用于直接执行 在 来源范围 - 它可能是也可能不是调用者的范围(见下面的警告)。
因此,这样的 script-block 文字必须 保存在变量中 或 传递给需要脚本块的命令 以便稍后执行。
如果没有,脚本块隐式输出到成功输出流,默认情况下输出到控制台(主机),导致它由 .ToString()
值,它只是脚本块的 逐字内容 ,不包括分隔符({
和 }
)。
例如:
# Script block literal is output by its *verbatim content* (without delimiters)
PS> { "Honey, I'm $HOME" }
"Honey, I'm $HOME"
为了正确使用脚本块,您必须执行它,通常使用&
:
# `& ` executes in a child scope of and
# `. ` executes directly in the scope of origin, typically the current scope.
PS> & { "Honey, I'm $HOME" }
Honey, I'm C:\Users\jdoe # e.g.
警告:
Script-block 文字 - 与使用 [scriptblock]::Create('...')
构造的脚本块不同 - 绑定到范围域(a.k.a “会话状态”),其中定义了它们。
这意味着:
Script-block 在模块外 定义的文字 ,当也从模块外调用时,在子范围内执行 运行 (&
) / 直接在 (.
) 调用者的 作用域中。
相比之下,script-block 在模块内部定义的文字 与该模块的作用域相关联],这意味着调用 - 无论从何处进行调用 from - 在该模块的 top-level 作用域(使用 .
)或其子作用域中执行( &
).
示例:
PS> $foo = 1; function Get-ScriptBlock { (++$foo) }; . Get-ScriptBlock
2
也就是说,在 non-module 范围域中创建的脚本块直接在 non-module 调用方的范围中使用 .
运行 调用。
PS> $foo = 1; $null = New-Module { $foo = 99; function Get-ScriptBlock { (++$foo) } }; . Get-ScriptBlock
100
也就是说,在 New-Module
创建的动态模块的范围域中创建的脚本块,在 该模块的 .
、运行 调用=96=] top-level 范围,即使它是从 non-module 调用者调用的。
我有一个 Pester It 块,如下所示:
It "should add a header" {
{
$DifferenceObject = Get-Content -Path $PathToFile1
Set-PowershellFile -Path $PathToFile2
$ReferencedObject = Get-Content -Path $PathToFile2
Compare-Object -ReferenceObject $ReferencedObject -DifferenceObject $DifferenceObject | should -be $null
}
}
Set-PowershellFile 只是用一些新文本更新文件。我认为上面的代码会执行以下操作,但我只想确认:
- 它获取位于 'PathToFile1' 的文件的内容
- 它使用 Set-PowershellFile 将文件设置为 'PathToFile2',然后获取该文件的新内容。
- 将新更新的文件与第一个文件的内容进行比较,确保它们相同。
这是正确的吗?当我 运行 我的单元测试时,在 Set-PowershellFile 中所做的文件更改不会持续存在,但单元测试通过了。我假设将此代码包装在 {} 中的 if 块内会导致同步行为,但不会 'commit' 文件更改。这些都正确吗?
Mathias R. Jessen 在评论中提供了关键指针 - 只需 省略 内部 {
和 }
- 但由于我之前已经看到了潜在的误解,因此值得深入挖掘:
虽然 { ... }
块是大多数 PowerShell 语句的常规部分,例如 foreach
和 if
, 孤立地 它们 不提供一个范围内的语句块立即执行,例如它在C#中的工作方式。
相反,{ ... }
隔离 是 PowerShell script block, i.e. a block of statements for later execution, on demand, either via &
, the call operator, for execution in a child scope of, or via .
, the dot-sourcing operator 的字面形式,用于直接执行 在 来源范围 - 它可能是也可能不是调用者的范围(见下面的警告)。
因此,这样的 script-block 文字必须 保存在变量中 或 传递给需要脚本块的命令 以便稍后执行。
如果没有,脚本块隐式输出到成功输出流,默认情况下输出到控制台(主机),导致它由 .ToString()
值,它只是脚本块的 逐字内容 ,不包括分隔符({
和 }
)。
例如:
# Script block literal is output by its *verbatim content* (without delimiters)
PS> { "Honey, I'm $HOME" }
"Honey, I'm $HOME"
为了正确使用脚本块,您必须执行它,通常使用&
:
# `& ` executes in a child scope of and
# `. ` executes directly in the scope of origin, typically the current scope.
PS> & { "Honey, I'm $HOME" }
Honey, I'm C:\Users\jdoe # e.g.
警告:
Script-block 文字 - 与使用 [scriptblock]::Create('...')
构造的脚本块不同 - 绑定到范围域(a.k.a “会话状态”),其中定义了它们。
这意味着:
Script-block 在模块外 定义的文字 ,当也从模块外调用时,在子范围内执行 运行 (
&
) / 直接在 (.
) 调用者的 作用域中。相比之下,script-block 在模块内部定义的文字 与该模块的作用域相关联],这意味着调用 - 无论从何处进行调用 from - 在该模块的 top-level 作用域(使用
.
)或其子作用域中执行(&
).
示例:
PS> $foo = 1; function Get-ScriptBlock { (++$foo) }; . Get-ScriptBlock
2
也就是说,在 non-module 范围域中创建的脚本块直接在 non-module 调用方的范围中使用 .
运行 调用。
PS> $foo = 1; $null = New-Module { $foo = 99; function Get-ScriptBlock { (++$foo) } }; . Get-ScriptBlock
100
也就是说,在 New-Module
创建的动态模块的范围域中创建的脚本块,在 该模块的 .
、运行 调用=96=] top-level 范围,即使它是从 non-module 调用者调用的。