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 只是用一些新文本更新文件。我认为上面的代码会执行以下操作,但我只想确认:

  1. 它获取位于 'PathToFile1'
  2. 的文件的内容
  3. 它使用 Set-PowershellFile 将文件设置为 'PathToFile2',然后获取该文件的新内容。
  4. 将新更新的文件与第一个文件的内容进行比较,确保它们相同。

这是正确的吗?当我 运行 我的单元测试时,在 Set-PowershellFile 中所做的文件更改不会持续存在,但单元测试通过了。我假设将此代码包装在 {} 中的 if 块内会导致同步行为,但不会 'commit' 文件更改。这些都正确吗?

Mathias R. Jessen 在评论中提供了关键指针 - 只需 省略 内部 {} - 但由于我之前已经看到了潜在的误解,因此值得深入挖掘:

虽然 { ... } 块是大多数 PowerShell 语句的常规部分,例如 foreachif 孤立地 它们 提供一个范围内的语句块立即执行,例如它在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 调用者调用的。