2

このスクリプトを実行すると、なぜ次のような動作になるのか疑問に思っています。PowerShell ISE (v4 ホスト) にスクリプトをロードし、Pester モジュールをロードしました。F5 キーを押してスクリプトを実行します。

function Test-Pester {
  throw("An error")
}

Describe "what happens when a function throws an error" {

  Context "we test with Should Throw" {

    It "Throws an error" {
      { Test-Pester } | Should Throw
    }
  }

  Context "we test using a try-catch construct" {

    $ErrorSeen = $false
    try {
      Test-Pester
    }
    catch {
      $ErrorSeen = $true
    }

    It "is handled by try-catch" {
      $ErrorSeen | Should Be $true
    }
  }

  Context "we test using trap" {

    trap {
      $ErrorSeen = $true
    }

    $ErrorSeen = $false

    Test-Pester

    It "is handled by trap" {
      $ErrorSeen | Should Be $true
    }
  }
}

次に、次の出力を取得します。

Describing what happens when a function throws an error
   Context we test with Should Throw
    [+] Throws an error 536ms
   Context we test using a try-catch construct
    [+] is handled by try-catch 246ms
   Context we test using trap
An error
At C:\Test-Pester.ps1:2 char:7
+       throw("An error")
+       ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (An error:String) [], RuntimeException
    + FullyQualifiedErrorId : An error

    [-] is handled by trap 702ms
      Expected: {True}
      But was:  {False}
      at line: 40 in C:\Test-Pester.ps1
      40:           $ErrorSeen | Should Be $true

質問

trap{}が最終テストで実行されていないように見えるのはなぜですか?

4

2 に答える 2

2

@PetSerAl と @Eris からのコメント/提案された回答に基づく、問題に対する 2 つの解決策を次に示します。また、この質問に対する回答を読み、感謝しています。

トラップ ブロック内の変数の割り当てがブロック外に表示されないのはなぜですか?

解決策 1

スクリプトに設定された変数はトラップ内で読み取ることができますが、トラップ内で行うことはすべて、その変数のコピーに対して発生します。つまり、トラップに対してローカルなスコープ内でのみ発生します。このソリューションでは、参照を評価し$ErrorSeenて、変数の値を設定すると、実際には親スコープに存在する変数の値を設定します。

トラップにa を追加するcontinueと、ErrorRecord の詳細が抑制され、テストの出力がクリーンアップされます。

Describe "what happens when a function throws an error" {
  Context "we test using trap" {

    $ErrorSeen = $false

    trap {
      Write-Warning "Error trapped"
      ([Ref]$ErrorSeen).Value = $true
      continue
    }

    Test-Pester

    It "is handled by trap" {
      $ErrorSeen | Should Be $true
    }
  }
}

解決策 2

最初の解決策と同じように、(1) 変数のスコープを明示的に設定することで問題を解決でき$ErrorSeenます (1) 変数を最初に作成するとき、および (2) 内で使用するときtrap {}。ここでは Script スコープを使用しましたが、Global も機能するようです。

ここでも同じ原則が適用されます。トラップ内の変数への変更が、変数のローカル コピーに対してのみ発生するという問題を回避する必要があります。

Describe "what happens when a function throws an error" {
  Context "we test using trap" {

    $Script:ErrorSeen = $false

    trap {
      Write-Warning "Error trapped"
      $Script:ErrorSeen = $true
      continue
    }

    Test-Pester

    It "is handled by trap" {
      $ErrorSeen | Should Be $true
    }
  }
}
于 2016-04-16T20:28:00.643 に答える
1

このブログによると、制御フローに対して何かを行うようにトラップに指示する必要があります。

[...] これをスクリプトとして実行すると、エラー メッセージと赤い PowerShell エラー メッセージの両方が表示されます。

. 'C:\Scripts\test.ps1'
Something terrible happened!
Attempted to divide by zero.
At C:\Scripts\test.ps1:2 Char:3
+ 1/ <<<< null

これは、トラップが実際には例外を処理しなかったためです。例外を処理するには、「Continue」ステートメントをトラップに追加する必要があります。

trap { 'Something terrible happened!'; continue }
1/$null

これで、トラップは期待どおりに機能します。トラップ スクリプト ブロックで指定したことはすべて実行され、PowerShell は例外を認識しなくなります。赤いエラー メッセージは表示されなくなりました。

于 2016-04-15T17:35:22.713 に答える