简体   繁体   English

Powershell 中的同步单元测试执行

[英]Synchronous unit test execution in Powershell

I've got a Pester It block, that looks like the below:我有一个 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 just updates a file with some new text. Set-PowershellFile 只是用一些新文本更新文件。 I thought that the above code would do the following but I just want to confirm:我认为上面的代码会执行以下操作,但我只想确认:

  1. It gets the content of a file located at 'PathToFile1'它获取位于“PathToFile1”的文件的内容
  2. It sets the file at 'PathToFile2' using Set-PowershellFile, then gets the new content of that file.它使用 Set-PowershellFile 将文件设置为“PathToFile2”,然后获取该文件的新内容。
  3. Compares the newly updated file to the content of the first file, making sure that they are the same.将新更新的文件与第一个文件的内容进行比较,确保它们相同。

Is this correct?这个对吗? When I run my unit tests, the file change made in Set-PowershellFile does not persist, but the unit test passes.当我运行单元测试时,在 Set-PowershellFile 中所做的文件更改不会持续存在,但单元测试通过了。 I assumed that wrapping this code inside the if block in {} causes the synchronous behavior but doesn't 'commit' the file changes.我假设将此代码包装在 {} 中的 if 块中会导致同步行为,但不会“提交”文件更改。 Is this all correct?这一切都正确吗?

Mathias R.马蒂亚斯 R。 Jessen provided the crucial pointer in a comment - simply omit the inner { and } - but since I've seen the underlying misconception before, it's worth digging deeper: Jessen在评论中提供了关键指针 - 只需省略内部{} - 但由于我之前已经看到了潜在的误解,因此值得深入挖掘:

While {... } blocks are a regular part of most PowerShell statements, such as foreach and if , in isolation they do not provide a scoped block of statements that are immediately executed , the way it would work in C#, for instance.虽然{... }块是大多数 PowerShell 语句的常规部分,例如foreachif ,但它们提供立即执行的范围语句块,例如它在C#中的工作方式。

Instead, {... } in isolation is the literal form of a PowerShell script block , ie a block of statements for later execution, on demand , either via & , the call operator , for execution in a child scope of , or via .相反, {... }孤立地是 PowerShell 脚本块的文字形式,即稍后执行的语句块,根据需要,通过&调用运算符,在子 scope 中执行,或通过. , the dot-sourcing operator , for execution directly in the scope of origin - which may or may not be the caller's scope (see caveat below). 点源运算符直接在原点 scope 中执行 - 这可能是也可能不是调用者的scope(请参阅下面的警告)。

Thus, such a script-block literal must either be saved in a variable or passed to a command expecting a script block in order to be executed later .因此,这样的脚本块文字必须要么保存在变量中,要么传递给需要脚本块的命令,以便稍后执行

Absent that, a script block is implicitly output to the success output stream , which by default goes to the console (host), causing it to be rendered by its .ToString() value, which is simply the verbatim content of the script block, excluding the delimiters ( { and } ). Absent that, a script block is implicitly output to the success output stream , which by default goes to the console (host), causing it to be rendered by its .ToString() value, which is simply the verbatim content of the script block,不包括分隔符( {} )。

For instance:例如:

# Script block literal is output by its *verbatim content* (without delimiters)
PS> { "Honey, I'm $HOME" }
 "Honey, I'm $HOME"

In order to use a script block properly, you must execute it , typically with & :为了正确使用脚本块,您必须执行,通常使用&

# `& ` 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.

Caveat :警告

Script-block literals - unlike script blocks constructed with [scriptblock]::Create('...') - are tied to the scope domain (aka "session state") in which they are defined .脚本块文字- 与使用[scriptblock]::Create('...')构建的脚本块不同 - 与定义它们的 scope 域(又名“会话状态”)相关联

This means:这表示:

  • Script-block literals defined outside a module , when also called from outside a module, do run in a child scope of ( & ) / directly in ( . ) the caller's scope.在模块外部定义的脚本块文字,当也从模块外部调用时,确实在 ( & ) 的子 scope 中运行/直接在 ( . )调用者的scope 中运行。

  • By contrast, script-block literals defined inside a module , are tied to that module's scope domain , meaning that an invocation - irrespective of where the call is made from - execute in that module's top-level scope (with . ) or a child scope thereof (with & ). By contrast, script-block literals defined inside a module , are tied to that module's scope domain , meaning that an invocation - irrespective of where the call is made from - execute in that module's top-level scope (with . ) or a child scope其中(带& )。

Examples:例子:

PS> $foo = 1; function Get-ScriptBlock { { (++$foo) } }; . (Get-ScriptBlock)
2

That is, the script block created in the non-module scope domain invoked with .即,在非模块 scope 域中创建的脚本块使用. ran directly in the non-module caller's scope.直接在非模块调用者的 scope 中运行。

PS> $foo = 1; $null = New-Module { $foo = 99; function Get-ScriptBlock { { (++$foo) } } }; . (Get-ScriptBlock)
100

That is, the script block created in the scope domain of the dynamic module created with New-Module , invoked with .也就是说,在使用New-Module创建的动态模块的 scope 域中创建的脚本块,使用 调用. , ran in that module's top-level scope, even though it was invoked from a non-module caller. ,在该模块的顶级 scope 中运行,即使它是从非模块调用者调用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM