From f63f2950f9bf17bf375223acee53eb85f68e8383 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 12 Aug 2021 10:11:13 -0700 Subject: [PATCH 1/4] Add more tests to validate the current command error handling behaviors --- .../Scripting/CommandErrorHandling.Tests.ps1 | 470 ++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 diff --git a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 new file mode 100644 index 00000000000..90d66861868 --- /dev/null +++ b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 @@ -0,0 +1,470 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe 'Command error handling in general' -Tag 'CI' { + + BeforeAll { + $pwsh = [PowerShell]::Create() + $pwsh.AddScript(@' + + function ThrowTerminatingError { + [CmdletBinding()] + param() + + $ex = [System.ArgumentException]::new('terminating-exception') + $er = [System.Management.Automation.ErrorRecord]::new($ex, 'ThrowTerminatingError:error', 'InvalidArgument', $null) + $PSCmdlet.ThrowTerminatingError($er) + + Write-Verbose -Verbose "verbose-message" + } + + function ErrorActionStop { + [CmdletBinding()] + param() + + Get-Command NonExist -ErrorAction Stop + Write-Verbose -Verbose "verbose-message" + } + + function ThrowException { + [CmdletBinding()] + param() + + throw 'throw-exception' + Write-Verbose -Verbose "verbose-message" + } + + function WriteErrorAPI { + [CmdletBinding()] + param() + + $ex = [System.ArgumentException]::new('arg-exception') + $er = [System.Management.Automation.ErrorRecord]::new($ex, 'WriteErrorAPI:error', 'InvalidArgument', $null) + $PSCmdlet.WriteError($er) + + Write-Verbose -Verbose "verbose-message" + } + + function WriteErrorCmdlet { + [CmdletBinding()] + param() + + Write-Error 'write-error-cmdlet' + Write-Verbose -Verbose "verbose-message" + } + + function MethodInvocationThrowException { + [CmdletBinding()] + param() + + ## This method call throws exception. + $iss = [initialsessionstate]::Create() + $iss.ImportPSModule($null) + + Write-Verbose -Verbose "verbose-message" + } + + function ExpressionThrowException { + [CmdletBinding()] + param() + + 1/0 ## throw exception. + Write-Verbose -Verbose "verbose-message" + } + +'@).Invoke() + + function RunCommand { + param( + [string] $Command, + [ValidateSet('Continue', 'Ignore', 'SilentlyContinue', 'Stop')] + [string] $ErrorAction + ) + + $pwsh.Commands.Clear() + $pwsh.Streams.ClearStreams() + $pwsh.AddCommand($command).AddParameter('ErrorAction', $ErrorAction).Invoke() + } + + function RunScript { + param([string] $Script) + + $pwsh.Commands.Clear() + $pwsh.Streams.ClearStreams() + $pwsh.AddScript($Script).Invoke() + } + + function GetLastError { + $pwsh.Commands.Clear() + $pwsh.AddCommand('Get-Error').Invoke() + } + + function ClearDollarError { + $pwsh.Commands.Clear() + $pwsh.AddScript('$Error.Clear()').Invoke() + } + } + + AfterAll { + $pwsh.Dispose() + } + + Context 'Terminating error' { + + It "'ThrowTerminatingError' stops execution with 'ActionPreference.' for error action" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ThrowTerminatingError' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException | Should -BeOfType 'System.ArgumentException' + $failure.Exception.InnerException.InnerException.Message | Should -BeExactly 'terminating-exception' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + } + + It "'-ErrorAction Stop' stops execution with 'ActionPreference.' for error action" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ErrorActionStop' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.ActionPreferenceStopException' + $failure.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly 'CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + } + + It "'throw' statement stops execution with 'ActionPreference.Continue' (the default error action)" { + $failure = $null + + try { + RunCommand -Command 'ThrowException' -ErrorAction 'Continue' + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.RuntimeException' + $failure.Exception.InnerException.Message | Should -BeExactly 'throw-exception' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + } + + <# The 'throw' statement is special, in that it can be suppressed by '-ErrorAction SilentlyContinue/Ignore' #> + It "'throw' statement continues execution with 'ActionPreference.'" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + $failure = $null + + try { + RunCommand -Command 'ThrowException' -ErrorAction $ErrorAction + } catch { + $failure = $_ + } + + $failure | Should -BeNullOrEmpty + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed 'throw' exception is not written to the error stream, not sure why but it's the current behavior. + $pwsh.Streams.Error.Count | Should -BeExactly 0 + + ## The suppressed 'throw' exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.FullyQualifiedErrorId | Should -BeExactly 'throw-exception' + } + + It "'throw' statement stops execution with 'ActionPreference.' when it's wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { ThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.FullyQualifiedErrorId }" + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' + } + + It "'throw' statement stops execution with 'ActionPreference.' when it's accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.FullyQualifiedErrorId; continue } ThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' + } + } + + Context 'Non-terminating error' { + + It "'WriteErrorAPI' continues execution with with 'ActionPreference.Continue' (the default error action)" { + RunCommand -Command 'WriteErrorAPI' -ErrorAction Continue + + $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'arg-exception' + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'WriteErrorAPI' continues execution with with 'ActionPreference.Ignore' without logging the error in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorAPI' -ErrorAction Ignore + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -BeNullOrEmpty + } + + It "'WriteErrorAPI' continues execution with with 'ActionPreference.SilentlyContinue' and logs the error in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorAPI' -ErrorAction SilentlyContinue + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -Not -BeNullOrEmpty + $lastErr.Exception.Message | Should -BeExactly 'arg-exception' + $lastErr.FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' + } + + It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.Continue' (the default error action)" { + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Continue + + $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'write-error-cmdlet' + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.Ignore' without logging the error in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Ignore + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -BeNullOrEmpty + } + + It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.SilentlyContinue' and logs the error in `$Error" { + ClearDollarError + RunCommand -Command 'WriteErrorCmdlet' -ErrorAction SilentlyContinue + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + $lastErr = GetLastError + $lastErr | Should -Not -BeNullOrEmpty + $lastErr.Exception.Message | Should -BeExactly 'write-error-cmdlet' + $lastErr.FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' + } + } + + Context 'Exception thrown from the method invocation or expression' { + + #region MethodInvocationThrowException + + It "'MethodInvocationThrowException' emits non-terminating error with 'ActionPreference.Continue' (the default error action)" { + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction 'Continue' + + $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' + + $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'MethodInvocationThrowException' emits no error with 'ActionPreference.'" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction $ErrorAction + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' + } + + It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.Stop'" { + $failure = $null + + try { + RunCommand -Command 'MethodInvocationThrowException' -ErrorAction Stop + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.ArgumentNullException' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + } + + It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.' when wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { MethodInvocationThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' + } + + It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.' when accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } MethodInvocationThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' + } + + #endregion + + #region ExpressionThrowException + + It "'ExpressionThrowException' emits non-terminating error with 'ActionPreference.Continue' (the default error action)" { + RunCommand -Command 'ExpressionThrowException' -ErrorAction 'Continue' + + $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error[0].Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' + + $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + } + + It "'ExpressionThrowException' emits no error with 'ActionPreference.'" -TestCases @( + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunCommand -Command 'ExpressionThrowException' -ErrorAction $ErrorAction + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' + + ## The suppressed exception is kept in '$Error' + $err = GetLastError + $err | Should -Not -BeNullOrEmpty + $err.Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' + } + + It "'ExpressionThrowException' emits terminating error with 'ActionPreference.Stop'" { + $failure = $null + + try { + RunCommand -Command 'ExpressionThrowException' -ErrorAction Stop + } catch { + $failure = $_ + } + + $failure | Should -Not -BeNullOrEmpty + $failure.Exception | Should -BeOfType 'System.Management.Automation.MethodInvocationException' + $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' + $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.DivideByZeroException' + + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + } + + It "'ExpressionThrowException' emits terminating error with 'ActionPreference.' when wrapped in 'try/catch'" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "try { ExpressionThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' + } + + It "'ExpressionThrowException' emits terminating error with 'ActionPreference.' when accompanied by 'trap' statement" -TestCases @( + @{ ErrorAction = 'Continue' } + @{ ErrorAction = 'Ignore' } + @{ ErrorAction = 'SilentlyContinue' } + ) { + param ($ErrorAction) + + RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } ExpressionThrowException -ErrorAction $ErrorAction" + + $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' + } + + #endregion + } +} From 468c8f080262d5d756746012e20be2a638e334d4 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 12 Aug 2021 15:18:02 -0700 Subject: [PATCH 2/4] Rename tests with better names --- .../Scripting/CommandErrorHandling.Tests.ps1 | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 index 90d66861868..780318b888a 100644 --- a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 +++ b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 @@ -111,7 +111,7 @@ Describe 'Command error handling in general' -Tag 'CI' { Context 'Terminating error' { - It "'ThrowTerminatingError' stops execution with 'ActionPreference.' for error action" -TestCases @( + It "'ThrowTerminatingError' should always stop execution even when the error action is ''" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } @@ -135,7 +135,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose.Count | Should -BeExactly 0 } - It "'-ErrorAction Stop' stops execution with 'ActionPreference.' for error action" -TestCases @( + It "'-ErrorAction Stop' should always stop execution even when the error action is ''" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } @@ -158,7 +158,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose.Count | Should -BeExactly 0 } - It "'throw' statement stops execution with 'ActionPreference.Continue' (the default error action)" { + It "'throw' statement should stop execution when running with the default error action ('Continue')" { $failure = $null try { @@ -176,7 +176,7 @@ Describe 'Command error handling in general' -Tag 'CI' { } <# The 'throw' statement is special, in that it can be suppressed by '-ErrorAction SilentlyContinue/Ignore' #> - It "'throw' statement continues execution with 'ActionPreference.'" -TestCases @( + It "'throw' statement doesn't stop execution when the error action is ''" -TestCases @( @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } ) { @@ -203,7 +203,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $err.FullyQualifiedErrorId | Should -BeExactly 'throw-exception' } - It "'throw' statement stops execution with 'ActionPreference.' when it's wrapped in 'try/catch'" -TestCases @( + It "'throw' statement should stop execution with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } ) { @@ -216,7 +216,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' } - It "'throw' statement stops execution with 'ActionPreference.' when it's accompanied by 'trap' statement" -TestCases @( + It "'throw' statement should stop execution with the error action '' when it's accompanied by 'trap' statement" -TestCases @( @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } ) { @@ -232,7 +232,7 @@ Describe 'Command error handling in general' -Tag 'CI' { Context 'Non-terminating error' { - It "'WriteErrorAPI' continues execution with with 'ActionPreference.Continue' (the default error action)" { + It "'WriteErrorAPI' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorAPI' -ErrorAction Continue $pwsh.Streams.Error.Count | Should -BeExactly 1 @@ -243,7 +243,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } - It "'WriteErrorAPI' continues execution with with 'ActionPreference.Ignore' without logging the error in `$Error" { + It "'WriteErrorAPI' doesn't stop execution with the error action 'Ignore' and the error doesn't get logged in `$Error" { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction Ignore @@ -255,7 +255,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $lastErr | Should -BeNullOrEmpty } - It "'WriteErrorAPI' continues execution with with 'ActionPreference.SilentlyContinue' and logs the error in `$Error" { + It "'WriteErrorAPI' doesn't stop execution with the error action 'SilentlyContinue' and the error gets logged in `$Error" { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction SilentlyContinue @@ -269,7 +269,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $lastErr.FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' } - It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.Continue' (the default error action)" { + It "'WriteErrorCmdlet' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Continue $pwsh.Streams.Error.Count | Should -BeExactly 1 @@ -280,7 +280,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } - It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.Ignore' without logging the error in `$Error" { + It "'WriteErrorCmdlet' doesn't stop execution with the error action 'Ignore' and the error doesn't get logged in `$Error" { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Ignore @@ -292,7 +292,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $lastErr | Should -BeNullOrEmpty } - It "'WriteErrorCmdlet' continues execution with with 'ActionPreference.SilentlyContinue' and logs the error in `$Error" { + It "'WriteErrorCmdlet' doesn't stop execution with the error action 'SilentlyContinue' and the error gets logged in `$Error" { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction SilentlyContinue @@ -311,7 +311,7 @@ Describe 'Command error handling in general' -Tag 'CI' { #region MethodInvocationThrowException - It "'MethodInvocationThrowException' emits non-terminating error with 'ActionPreference.Continue' (the default error action)" { + It "'MethodInvocationThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'MethodInvocationThrowException' -ErrorAction 'Continue' $pwsh.Streams.Error.Count | Should -BeExactly 1 @@ -321,7 +321,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } - It "'MethodInvocationThrowException' emits no error with 'ActionPreference.'" -TestCases @( + It "'MethodInvocationThrowException' emits no error with the error action ''" -TestCases @( @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } ) { @@ -339,7 +339,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $err.FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' } - It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.Stop'" { + It "'MethodInvocationThrowException' emits terminating error with the error action 'Stop'" { $failure = $null try { @@ -356,7 +356,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose.Count | Should -BeExactly 0 } - It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.' when wrapped in 'try/catch'" -TestCases @( + It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } @@ -371,7 +371,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' } - It "'MethodInvocationThrowException' emits terminating error with 'ActionPreference.' when accompanied by 'trap' statement" -TestCases @( + It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's accompanied by 'trap' statement" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } @@ -390,7 +390,7 @@ Describe 'Command error handling in general' -Tag 'CI' { #region ExpressionThrowException - It "'ExpressionThrowException' emits non-terminating error with 'ActionPreference.Continue' (the default error action)" { + It "'ExpressionThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'ExpressionThrowException' -ErrorAction 'Continue' $pwsh.Streams.Error.Count | Should -BeExactly 1 @@ -400,7 +400,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } - It "'ExpressionThrowException' emits no error with 'ActionPreference.'" -TestCases @( + It "'ExpressionThrowException' emits no error with the error action ''" -TestCases @( @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } ) { @@ -418,7 +418,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $err.Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' } - It "'ExpressionThrowException' emits terminating error with 'ActionPreference.Stop'" { + It "'ExpressionThrowException' emits terminating error with the error action 'Stop'" { $failure = $null try { @@ -435,7 +435,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Verbose.Count | Should -BeExactly 0 } - It "'ExpressionThrowException' emits terminating error with 'ActionPreference.' when wrapped in 'try/catch'" -TestCases @( + It "'ExpressionThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } @@ -450,7 +450,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' } - It "'ExpressionThrowException' emits terminating error with 'ActionPreference.' when accompanied by 'trap' statement" -TestCases @( + It "'ExpressionThrowException' emits terminating error with the error action '' when it's accompanied by 'trap' statement" -TestCases @( @{ ErrorAction = 'Continue' } @{ ErrorAction = 'Ignore' } @{ ErrorAction = 'SilentlyContinue' } From ac4e57a3b08576da42b9b17917fde486dc24f077 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Fri, 13 Aug 2021 09:19:39 -0700 Subject: [PATCH 3/4] Use -Be instead of -BeExactly for number comparison --- .../Scripting/CommandErrorHandling.Tests.ps1 | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 index 780318b888a..cccdd07ffb1 100644 --- a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 +++ b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 @@ -132,7 +132,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException.InnerException | Should -BeOfType 'System.ArgumentException' $failure.Exception.InnerException.InnerException.Message | Should -BeExactly 'terminating-exception' - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 } It "'-ErrorAction Stop' should always stop execution even when the error action is ''" -TestCases @( @@ -155,7 +155,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.ActionPreferenceStopException' $failure.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly 'CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand' - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 } It "'throw' statement should stop execution when running with the default error action ('Continue')" { @@ -172,7 +172,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.RuntimeException' $failure.Exception.InnerException.Message | Should -BeExactly 'throw-exception' - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 } <# The 'throw' statement is special, in that it can be suppressed by '-ErrorAction SilentlyContinue/Ignore' #> @@ -191,11 +191,11 @@ Describe 'Command error handling in general' -Tag 'CI' { } $failure | Should -BeNullOrEmpty - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed 'throw' exception is not written to the error stream, not sure why but it's the current behavior. - $pwsh.Streams.Error.Count | Should -BeExactly 0 + $pwsh.Streams.Error.Count | Should -Be 0 ## The suppressed 'throw' exception is kept in '$Error' $err = GetLastError @@ -211,8 +211,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { ThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.FullyQualifiedErrorId }" - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' } @@ -224,8 +224,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.FullyQualifiedErrorId; continue } ThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' } } @@ -235,11 +235,11 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'WriteErrorAPI' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorAPI' -ErrorAction Continue - $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 1 $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'arg-exception' $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -247,8 +247,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction Ignore - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -259,8 +259,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction SilentlyContinue - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -272,11 +272,11 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'WriteErrorCmdlet' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Continue - $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 1 $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'write-error-cmdlet' $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -284,8 +284,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Ignore - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -296,8 +296,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction SilentlyContinue - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -314,7 +314,7 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'MethodInvocationThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'MethodInvocationThrowException' -ErrorAction 'Continue' - $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 1 $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 @@ -329,8 +329,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunCommand -Command 'MethodInvocationThrowException' -ErrorAction $ErrorAction - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed exception is kept in '$Error' @@ -353,7 +353,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.ArgumentNullException' - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 } It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @@ -365,9 +365,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { MethodInvocationThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' } @@ -380,9 +380,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } MethodInvocationThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' } @@ -393,7 +393,7 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'ExpressionThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'ExpressionThrowException' -ErrorAction 'Continue' - $pwsh.Streams.Error.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 1 $pwsh.Streams.Error[0].Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 @@ -408,8 +408,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunCommand -Command 'ExpressionThrowException' -ErrorAction $ErrorAction - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed exception is kept in '$Error' @@ -432,7 +432,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.DivideByZeroException' - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 } It "'ExpressionThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @@ -444,9 +444,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { ExpressionThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' } @@ -459,9 +459,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } ExpressionThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Error.Count | Should -BeExactly 0 - $pwsh.Streams.Verbose.Count | Should -BeExactly 0 - $pwsh.Streams.Debug.Count | Should -BeExactly 1 + $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Debug.Count | Should -Be 1 $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' } From 8cf0dd0e8a7a8b4c780a00c229633ffbb632e993 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Sat, 14 Aug 2021 13:53:08 -0700 Subject: [PATCH 4/4] Address Aditya's comments --- .../Scripting/CommandErrorHandling.Tests.ps1 | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 index cccdd07ffb1..fe2ed803ecf 100644 --- a/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 +++ b/test/powershell/Language/Scripting/CommandErrorHandling.Tests.ps1 @@ -132,7 +132,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException.InnerException | Should -BeOfType 'System.ArgumentException' $failure.Exception.InnerException.InnerException.Message | Should -BeExactly 'terminating-exception' - $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 } It "'-ErrorAction Stop' should always stop execution even when the error action is ''" -TestCases @( @@ -155,7 +155,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.ActionPreferenceStopException' $failure.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly 'CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand' - $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 } It "'throw' statement should stop execution when running with the default error action ('Continue')" { @@ -172,7 +172,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.RuntimeException' $failure.Exception.InnerException.Message | Should -BeExactly 'throw-exception' - $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 } <# The 'throw' statement is special, in that it can be suppressed by '-ErrorAction SilentlyContinue/Ignore' #> @@ -191,11 +191,11 @@ Describe 'Command error handling in general' -Tag 'CI' { } $failure | Should -BeNullOrEmpty - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed 'throw' exception is not written to the error stream, not sure why but it's the current behavior. - $pwsh.Streams.Error.Count | Should -Be 0 + $pwsh.Streams.Error | Should -HaveCount 0 ## The suppressed 'throw' exception is kept in '$Error' $err = GetLastError @@ -211,8 +211,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { ThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.FullyQualifiedErrorId }" - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' } @@ -224,8 +224,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.FullyQualifiedErrorId; continue } ThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'throw-exception' } } @@ -235,11 +235,11 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'WriteErrorAPI' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorAPI' -ErrorAction Continue - $pwsh.Streams.Error.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 1 $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'arg-exception' $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'WriteErrorAPI:error,WriteErrorAPI' - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -247,8 +247,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction Ignore - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -259,8 +259,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorAPI' -ErrorAction SilentlyContinue - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -272,11 +272,11 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'WriteErrorCmdlet' doesn't stop execution with the default error action ('Continue')" { RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Continue - $pwsh.Streams.Error.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 1 $pwsh.Streams.Error[0].Exception.Message | Should -BeExactly 'write-error-cmdlet' $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'Microsoft.PowerShell.Commands.WriteErrorException,WriteErrorCmdlet' - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -284,8 +284,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction Ignore - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -296,8 +296,8 @@ Describe 'Command error handling in general' -Tag 'CI' { ClearDollarError RunCommand -Command 'WriteErrorCmdlet' -ErrorAction SilentlyContinue - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' $lastErr = GetLastError @@ -314,10 +314,10 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'MethodInvocationThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'MethodInvocationThrowException' -ErrorAction 'Continue' - $pwsh.Streams.Error.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 1 $pwsh.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'ArgumentNullException' - $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -329,8 +329,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunCommand -Command 'MethodInvocationThrowException' -ErrorAction $ErrorAction - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed exception is kept in '$Error' @@ -353,7 +353,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.ArgumentNullException' - $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 } It "'MethodInvocationThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @@ -365,9 +365,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { MethodInvocationThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' } @@ -380,9 +380,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } MethodInvocationThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'System.ArgumentNullException' } @@ -393,10 +393,10 @@ Describe 'Command error handling in general' -Tag 'CI' { It "'ExpressionThrowException' emits non-terminating error with the default error action ('Continue')" { RunCommand -Command 'ExpressionThrowException' -ErrorAction 'Continue' - $pwsh.Streams.Error.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 1 $pwsh.Streams.Error[0].Exception.InnerException | Should -BeOfType 'System.DivideByZeroException' - $pwsh.Streams.Verbose.Count | Should -BeLikeExactly 1 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' } @@ -408,8 +408,8 @@ Describe 'Command error handling in general' -Tag 'CI' { RunCommand -Command 'ExpressionThrowException' -ErrorAction $ErrorAction - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 1 $pwsh.Streams.Verbose | Should -BeExactly 'verbose-message' ## The suppressed exception is kept in '$Error' @@ -432,7 +432,7 @@ Describe 'Command error handling in general' -Tag 'CI' { $failure.Exception.InnerException | Should -BeOfType 'System.Management.Automation.CmdletInvocationException' $failure.Exception.InnerException.InnerException.InnerException | Should -BeOfType 'System.DivideByZeroException' - $pwsh.Streams.Verbose.Count | Should -Be 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 } It "'ExpressionThrowException' emits terminating error with the error action '' when it's wrapped in 'try/catch'" -TestCases @( @@ -444,9 +444,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "try { ExpressionThrowException -ErrorAction $ErrorAction } catch { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName }" - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' } @@ -459,9 +459,9 @@ Describe 'Command error handling in general' -Tag 'CI' { RunScript -Script "trap { Write-Debug -Debug `$_.Exception.InnerException.GetType().FullName; continue } ExpressionThrowException -ErrorAction $ErrorAction" - $pwsh.Streams.Error.Count | Should -Be 0 - $pwsh.Streams.Verbose.Count | Should -Be 0 - $pwsh.Streams.Debug.Count | Should -Be 1 + $pwsh.Streams.Error | Should -HaveCount 0 + $pwsh.Streams.Verbose | Should -HaveCount 0 + $pwsh.Streams.Debug | Should -HaveCount 1 $pwsh.Streams.Debug | Should -BeExactly 'System.DivideByZeroException' }