diff --git a/src/Pester.RSpec.ps1 b/src/Pester.RSpec.ps1 index bf83c9d18..f21f1a0b8 100644 --- a/src/Pester.RSpec.ps1 +++ b/src/Pester.RSpec.ps1 @@ -389,6 +389,9 @@ function New-PesterConfiguration { ErrorAction: Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test. Default value: 'Stop' + DisableV5: Disables usage of Should -Be assertions, that are replaced by Should-Be in version 6. + Default value: $false + Debug: ShowFullErrors: Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. Default value: $false diff --git a/src/csharp/Pester/ShouldConfiguration.cs b/src/csharp/Pester/ShouldConfiguration.cs index 551df69c4..bd658190f 100644 --- a/src/csharp/Pester/ShouldConfiguration.cs +++ b/src/csharp/Pester/ShouldConfiguration.cs @@ -22,6 +22,7 @@ namespace Pester public class ShouldConfiguration : ConfigurationSection { private StringOption _errorAction; + private BoolOption _disableV5; public static ShouldConfiguration Default { get { return new ShouldConfiguration(); } } @@ -33,11 +34,13 @@ public static ShouldConfiguration ShallowClone(ShouldConfiguration configuration public ShouldConfiguration() : base("Should configuration.") { ErrorAction = new StringOption("Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test.", "Stop"); + DisableV5 = new BoolOption("Disables usage of Should -Be assertions, that are replaced by Should-Be in version 6.", false); } public ShouldConfiguration(IDictionary configuration) : this() { configuration?.AssignObjectIfNotNull(nameof(ErrorAction), v => ErrorAction = v); + configuration?.AssignValueIfNotNull(nameof(DisableV5), v => DisableV5 = v); } public StringOption ErrorAction @@ -55,5 +58,21 @@ public StringOption ErrorAction } } } + + public BoolOption DisableV5 + { + get { return _disableV5; } + set + { + if (_disableV5 == null) + { + _disableV5 = value; + } + else + { + _disableV5 = new BoolOption(_disableV5, value.Value); + } + } + } } } diff --git a/src/functions/assertions/Should.ps1 b/src/functions/assertions/Should.ps1 index c130e6a64..fc0130d4d 100644 --- a/src/functions/assertions/Should.ps1 +++ b/src/functions/assertions/Should.ps1 @@ -122,18 +122,22 @@ function Should { $shouldThrow = 'Stop' -eq $PSBoundParameters["ErrorAction"] } + # first check if we are in the context of Pester, if not we will always throw, and won't disable Should: + # This check is slightly hacky, here we are reaching out the caller session state and + # look for $______parameters which we know we are using inside of the Pester runtime to + # keep the current invocation context, when we find it, we are able to add non-terminating + # errors without throwing and terminating the test. + $pesterRuntimeInvocationContext = $PSCmdlet.SessionState.PSVariable.GetValue('______parameters') + $isInsidePesterRuntime = $null -ne $pesterRuntimeInvocationContext + + if ($isInsidePesterRuntime -and $pesterRuntimeInvocationContext.Configuration.Should.DisableV5.Value) { + throw "Pester Should -Be syntax is disabled. Use Should-Be (without space), or enable it by setting: `$PesterPreference.Should.DisableV5 = `$false" + } + if ($null -eq $shouldThrow -or -not $shouldThrow) { # we are sure that we either: # - should not throw because of explicit ErrorAction, and need to figure out a place where to collect the error # - or we don't know what to do yet and need to figure out what to do based on the context and settings - - # first check if we are in the context of Pester, if not we will always throw: - # this is slightly hacky, here we are reaching out the the caller session state and - # look for $______parameters which we know we are using inside of the Pester runtime to - # keep the current invocation context, when we find it, we are able to add non-terminating - # errors without throwing and terminating the test - $pesterRuntimeInvocationContext = $PSCmdlet.SessionState.PSVariable.GetValue('______parameters') - $isInsidePesterRuntime = $null -ne $pesterRuntimeInvocationContext if (-not $isInsidePesterRuntime) { $shouldThrow = $true } diff --git a/tst/Pester.RSpec.Configuration.ts.ps1 b/tst/Pester.RSpec.Configuration.ts.ps1 index 7dc00b467..1447fd98d 100644 --- a/tst/Pester.RSpec.Configuration.ts.ps1 +++ b/tst/Pester.RSpec.Configuration.ts.ps1 @@ -135,6 +135,10 @@ i -PassThru:$PassThru { [PesterConfiguration]::Default.Should.ErrorAction.Value | Verify-Equal 'Stop' } + t "Should.DisableV5 is `$false" { + [PesterConfiguration]::Default.Should.DisableV5.Value | Verify-Equal $false + } + # Debug configuration t "Debug.ShowFullErrors is `$false" { [PesterConfiguration]::Default.Debug.ShowFullErrors.Value | Verify-False @@ -1140,7 +1144,7 @@ i -PassThru:$PassThru { Throw = $true } Output = @{ - CIFormat = 'None' + CIFormat = 'None' CILogLevel = 'Something' } } @@ -1152,7 +1156,7 @@ i -PassThru:$PassThru { b 'Output.RenderMode' { t 'Output.RenderMode is Plaintext when set to Auto (default) and env:NO_COLOR is set' { $c = [PesterConfiguration] @{ - Run = @{ + Run = @{ ScriptBlock = { } PassThru = $true } @@ -1225,7 +1229,7 @@ i -PassThru:$PassThru { $pesterPath = Get-Module Pester | Select-Object -ExpandProperty Path try { $ps = [PowerShell]::Create() - $ps.AddCommand('Set-StrictMode').AddParameter('Version','Latest') > $null + $ps.AddCommand('Set-StrictMode').AddParameter('Version', 'Latest') > $null $ps.AddStatement().AddScript("Import-Module '$pesterPath' -Force") > $null $ps.AddStatement().AddScript('$c = [PesterConfiguration]@{Run = @{ScriptBlock={ describe "d1" { it "i1" { } } };PassThru=$true};Output=@{RenderMode="Auto"}}') > $null $ps.AddStatement().AddScript('Invoke-Pester -Configuration $c') > $null @@ -1243,7 +1247,7 @@ i -PassThru:$PassThru { t 'Each non-Auto option can be set and updated' { $c = [PesterConfiguration] @{ - Run = @{ + Run = @{ ScriptBlock = { } PassThru = $true } @@ -1277,7 +1281,8 @@ i -PassThru:$PassThru { try { Invoke-Pester -Configuration $c $true | Verify-False # Should not get here - } catch { + } + catch { $_.Exception.Message -match "Output.RenderMode must be .* it was 'Something'" | Verify-True $failed = $true } @@ -1323,4 +1328,41 @@ i -PassThru:$PassThru { { Invoke-Pester -Configuration $c } | Verify-Throw } } + + b "Should.DisableV5" { + t "Disabling V5 assertions makes Should -Be throw" { + $c = [PesterConfiguration]@{ + Run = @{ + ScriptBlock = { Describe 'a' { It 'b' { 1 | Should -Be 1 } } } + PassThru = $true + } + Should = @{ + DisableV5 = $true + } + Output = @{ + CIFormat = 'None' + } + } + + $r = Invoke-Pester -Configuration $c + $err = $r.Containers.Blocks.Tests.ErrorRecord + + $err.Exception.Message | Verify-Equal 'Pester Should -Be syntax is disabled. Use Should-Be (without space), or enable it by setting: $PesterPreference.Should.DisableV5 = $false' + } + + t "Enabling V5 assertions makes Should -Be pass" { + $c = [PesterConfiguration]@{ + Run = @{ + ScriptBlock = { Describe 'a' { It 'b' { 1 | Should -Be 1 } } } + PassThru = $true + } + Should = @{ + DisableV5 = $false + } + } + + $r = Invoke-Pester -Configuration $c + $r.Result | Verify-Equal "Passed" + } + } }