From 42f63fa1ffbfe51d47d40c750b1c819b4d218a59 Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Tue, 5 Mar 2019 14:28:35 -0700 Subject: [PATCH 1/7] Migrate Pester version detection into an InovkePester stub script (#1776) * Migrate Pester version detection into an InovkePester stub script * Move TestName warning into script * Improve stub script, move module loaded check to beginning * Address Codacy issue * Address PR feedback * Move TestName check before LineNumber in case of multiple blocks/line --- .../InvokePesterStub.ps1 | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 module/PowerShellEditorServices/InvokePesterStub.ps1 diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 new file mode 100755 index 000000000..8b6f204cc --- /dev/null +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -0,0 +1,82 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Stub around Invoke-Pester command used by VSCode PowerShell extension. +.DESCRIPTION + The stub checks the version of Pester and if >= 4.6.0, invokes Pester + using the LineNumber parameter (if specified). Otherwise, it invokes + using the TestName parameter (if specified). If the All parameter + is specified, then all the tests are invoked in the specifed file. + Finally, if none of these three parameters are specified, all tests + are invoked and a warning is issued indicating what the user can do + to allow invocation of individual Describe blocks. +.EXAMPLE + PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1 -LineNumber 14 + Invokes a specific test by line number in the specified file. +.EXAMPLE + PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1 -TestName 'Foo Tests' + Invokes a specific test by test name in the specified file. +.EXAMPLE + PS C:\> .\InvokePesterStub.ps1 ~\project\test\foo.tests.ps1 -All + Invokes all tests in the specified file. +.INPUTS + None +.OUTPUTS + None +#> +param( + # Specifies the path to the test script. + [Parameter(Position=0, Mandatory)] + [ValidateNotNullOrEmpty()] + [string] + $ScriptPath, + + # Specifies the name of the test taken from the Describe block's name. + [Parameter()] + [string] + $TestName, + + # Specifies the starting line number of the DescribeBlock. This feature requires + # Pester 4.6.0 or higher. + [Parameter()] + [ValidatePattern('\d*')] + [string] + $LineNumber, + + # If specified, executes all the tests in the specified test script. + [Parameter()] + [switch] + $All +) + +$pesterModule = Microsoft.PowerShell.Core\Get-Module Pester +if (!$pesterModule) { + Write-Output "Importing Pester module..." + $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru + if (!$pesterModule) { + # If we still don't have an imported Pester module, that is (most likely) because Pester is not installed. + Write-Warning "Failed to import the Pester module. You must install Pester to run or debug Pester tests." + Write-Warning "You can install Pester by executing: Install-Module Pester -Scope CurrentUser -Force" + return + } +} + +if ($All) { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} +} +elseif ($TestName) { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -TestName $TestName +} +elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption (New-PesterOption -ScriptBlockFilter @{ + IncludeVSCodeMarker=$true; Line=$LineNumber; Path=$ScriptPath}) +} +else { + # We get here when the TestName expression is of type ExpandableStringExpressionAst. + # PSES will not attempt to "evaluate" the expression so it returns null for the TestName. + Write-Warning "The Describe block's TestName cannot be evaluated. EXECUTING ALL TESTS instead." + Write-Warning "To avoid this, install Pester >= 4.6.0 or remove any expressions in the TestName." + + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} +} From c65eb9fbf55a8957d4063ae4238bffaaae8c23ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 12 Mar 2020 20:03:57 +0100 Subject: [PATCH 2/7] Run single Pester test (#2441) * Run single test * Add options for code lens and verbosity * Rename Pester options to enableLegacyCodeLens and outputVerbosity * change to use Co-authored-by: Tyler Leonhardt --- .../InvokePesterStub.ps1 | 86 ++++++++++++++++--- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index 8b6f204cc..d9aa31a13 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -47,36 +47,100 @@ param( # If specified, executes all the tests in the specified test script. [Parameter()] [switch] - $All + $All, + + [Parameter()] + [switch] $MinimumVersion5, + + [Parameter(Mandatory)] + [string] $Output ) $pesterModule = Microsoft.PowerShell.Core\Get-Module Pester +# add one line, so the subsequent output is not shifted to the side +Write-Output '' if (!$pesterModule) { Write-Output "Importing Pester module..." - $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru + $minimumVersion = if ($MinimumVersion5) { "5.0.0" } else { "0.0.0" } + $versionMessage = " version $minimumVersion" + $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru -MinimumVersion $minimumVersion if (!$pesterModule) { # If we still don't have an imported Pester module, that is (most likely) because Pester is not installed. - Write-Warning "Failed to import the Pester module. You must install Pester to run or debug Pester tests." - Write-Warning "You can install Pester by executing: Install-Module Pester -Scope CurrentUser -Force" + Write-Warning "Failed to import Pester$(if ($MinimumVersion5){ $versionMessage }). You must install Pester module to run or debug Pester tests." + Write-Warning "You can install Pester by executing: Install-Module Pester $(if ($MinimumVersion5) {"-MinimumVersion 5.0.0" }) -Scope CurrentUser -Force" return } } -if ($All) { - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} +$pester4Output = switch ($Output) { + "None" { "None" } + "Minimal" { "Fails" } + default { "All" } } -elseif ($TestName) { - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -TestName $TestName + +if ($MinimumVersion5 -and $pesterModule.Version -lt "5.0.0") { + Write-Warning "Pester 5.0.0 or newer is required because setting PowerShell > Pester: Enable Legacy Code Lens is disabled, but Pester $($pesterModule.Version) is loaded. Some of the code lense features might not work as expected." +} + + +if ($All) { + if ($pesterModule.Version -ge '5.0.0') { + $configuration = @{ + Run = @{ + Path = $ScriptPath + } + } + # only override this if user asks us to do it, to allow Pester to pick up + # $PesterPreference from caller context and merge it with the configuration + # we provide below, this way user can specify his output (and other) settings + # using the standard [PesterConfiguration] object, and we can avoid providing + # settings for everything + if ("FromPreference" -ne $Output) { + $configuration.Add('Output', @{ Verbosity = $Output }) + } + Pester\Invoke-Pester -Configuration $configuration | Out-Null + } + else { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -Show $pester4Output + } } elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { - Pester\Invoke-Pester -Script $ScriptPath -PesterOption (New-PesterOption -ScriptBlockFilter @{ - IncludeVSCodeMarker=$true; Line=$LineNumber; Path=$ScriptPath}) + if ($pesterModule.Version -ge '5.0.0') { + $configuration = @{ + Run = @{ + Path = $ScriptPath + } + Filter = @{ + Line = "${ScriptPath}:$LineNumber" + } + } + if ("FromPreference" -ne $Output) { + $configuration.Add('Output', @{ Verbosity = $Output }) + } + Pester\Invoke-Pester -Configuration $configuration | Out-Null + } + else { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption (New-PesterOption -ScriptBlockFilter @{ + IncludeVSCodeMarker=$true; Line=$LineNumber; Path=$ScriptPath}) -Show $pester4Output + } +} +elseif ($TestName) { + if ($pesterModule.Version -ge '5.0.0') { + throw "Running tests by test name is unsafe. This should not trigger for Pester 5." + } + else { + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -TestName $TestName -Show $pester4Output + } } else { + if ($pesterModule.Version -ge '5.0.0') { + throw "Running tests by expandable string is unsafe. This should not trigger for Pester 5." + } + # We get here when the TestName expression is of type ExpandableStringExpressionAst. # PSES will not attempt to "evaluate" the expression so it returns null for the TestName. Write-Warning "The Describe block's TestName cannot be evaluated. EXECUTING ALL TESTS instead." Write-Warning "To avoid this, install Pester >= 4.6.0 or remove any expressions in the TestName." - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -Show $pester4Output } From fac7702ccbdb76aeb804a120ebedb80ab43600c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 7 Apr 2020 16:14:11 +0200 Subject: [PATCH 3/7] Fix Pester code lense (#2606) * Fix renamed setting * Fall through when legacy option is disablebd but Pester 5 is not found --- .../InvokePesterStub.ps1 | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index d9aa31a13..cdb6cb121 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -59,15 +59,20 @@ param( $pesterModule = Microsoft.PowerShell.Core\Get-Module Pester # add one line, so the subsequent output is not shifted to the side Write-Output '' + if (!$pesterModule) { Write-Output "Importing Pester module..." - $minimumVersion = if ($MinimumVersion5) { "5.0.0" } else { "0.0.0" } - $versionMessage = " version $minimumVersion" - $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru -MinimumVersion $minimumVersion + if ($MinimumVersion5) { + $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru -MinimumVersion 5.0.0 + } + + if (!$pesterModule) { + $pesterModule = Microsoft.PowerShell.Core\Import-Module Pester -ErrorAction Ignore -PassThru + } + if (!$pesterModule) { - # If we still don't have an imported Pester module, that is (most likely) because Pester is not installed. - Write-Warning "Failed to import Pester$(if ($MinimumVersion5){ $versionMessage }). You must install Pester module to run or debug Pester tests." - Write-Warning "You can install Pester by executing: Install-Module Pester $(if ($MinimumVersion5) {"-MinimumVersion 5.0.0" }) -Scope CurrentUser -Force" + Write-Warning "Failed to import Pester. You must install Pester module to run or debug Pester tests." + Write-Warning "$(if ($MinimumVersion5) {"Recommended version to install is Pester 5.0.0 or newer. "})You can install Pester by executing: Install-Module Pester$(if ($MinimumVersion5) {" -MinimumVersion 5.0.0" }) -Scope CurrentUser -Force" return } } @@ -79,7 +84,7 @@ $pester4Output = switch ($Output) { } if ($MinimumVersion5 -and $pesterModule.Version -lt "5.0.0") { - Write-Warning "Pester 5.0.0 or newer is required because setting PowerShell > Pester: Enable Legacy Code Lens is disabled, but Pester $($pesterModule.Version) is loaded. Some of the code lense features might not work as expected." + Write-Warning "Pester 5.0.0 or newer is required because setting PowerShell > Pester: Use Legacy Code Lens is disabled, but Pester $($pesterModule.Version) is loaded. Some of the code lense features might not work as expected." } From 4b3c3dc9924dfe014b7c99df66563d396cff7f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 5 May 2020 00:44:28 +0200 Subject: [PATCH 4/7] Fix Pester invocation for 3x versions (#2676) --- module/PowerShellEditorServices/InvokePesterStub.ps1 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index cdb6cb121..b1bcb75f6 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -105,9 +105,19 @@ if ($All) { } Pester\Invoke-Pester -Configuration $configuration | Out-Null } - else { + elseif ($pesterModule.Version -ge '3.4.5') { + # -Show was introduced in 3.4.5 Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -Show $pester4Output } + elseif ($pesterModule.Version -ge '3.4.0') { + # -PesterOption was introduced before 3.4.0, and VSCodeMarker in 4.0.3-rc, + # but because no-one checks the integrity of this hashtable we can call all of the versions + # down to 3.4.0 like this + Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} + } + else { + Pester\Invoke-Pester -Script $ScriptPath + } } elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { if ($pesterModule.Version -ge '5.0.0') { From 68cb5578aaed405a357faeb921b991494a12a654 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Mon, 1 Jun 2020 09:06:24 -0700 Subject: [PATCH 5/7] Support adding an OutputFile and allow running from command pallet (#2730) * Support adding OutputPath and run file * refactor all logic --- .../InvokePesterStub.ps1 | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index b1bcb75f6..d023c8981 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -53,7 +53,10 @@ param( [switch] $MinimumVersion5, [Parameter(Mandatory)] - [string] $Output + [string] $Output, + + [Parameter()] + [string] $OutputPath ) $pesterModule = Microsoft.PowerShell.Core\Get-Module Pester @@ -103,6 +106,14 @@ if ($All) { if ("FromPreference" -ne $Output) { $configuration.Add('Output', @{ Verbosity = $Output }) } + + if ($OutputPath) { + $configuration.Add('TestResult', @{ + Enabled = $true + OutputFormat = "NUnit2.5" + OutputPath = $OutputPath + }) + } Pester\Invoke-Pester -Configuration $configuration | Out-Null } elseif ($pesterModule.Version -ge '3.4.5') { @@ -132,6 +143,15 @@ elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { if ("FromPreference" -ne $Output) { $configuration.Add('Output', @{ Verbosity = $Output }) } + + if ($OutputPath) { + $configuration.Add('TestResult', @{ + Enabled = $true + OutputFormat = "NUnit2.5" + OutputPath = $OutputPath + }) + } + Pester\Invoke-Pester -Configuration $configuration | Out-Null } else { From 8194beacce8befe7b6955c8b7fe04662f9d11f11 Mon Sep 17 00:00:00 2001 From: EmmanuelPineiro Date: Fri, 14 Aug 2020 06:42:41 -0700 Subject: [PATCH 6/7] Fixed crash when running pester older than 3.4.5 (#2888) * Fixed crash when running pester older than 3.4.5 Calling Invoke-Pester with the -show param was breaking tests if running a version of pester older than 3.4.5 Moved logic for building spalt to call invoke-pester into a function and only added the show parameter if running pester 3.4.5 or newer * Update InvokePesterStub.ps1 Co-authored-by: Tyler James Leonhardt * Update InvokePesterStub.ps1 Co-authored-by: Tyler James Leonhardt Co-authored-by: Tyler James Leonhardt --- .../InvokePesterStub.ps1 | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index d023c8981..8f7eb94fd 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -87,10 +87,30 @@ $pester4Output = switch ($Output) { } if ($MinimumVersion5 -and $pesterModule.Version -lt "5.0.0") { - Write-Warning "Pester 5.0.0 or newer is required because setting PowerShell > Pester: Use Legacy Code Lens is disabled, but Pester $($pesterModule.Version) is loaded. Some of the code lense features might not work as expected." + Write-Warning "Pester 5.0.0 or newer is required because setting PowerShell > Pester: Use Legacy Code Lens is disabled, but Pester $($pesterModule.Version) is loaded. Some of the code lens features might not work as expected." } +function Get-InvokePesterParams { + $invokePesterParams = @{ + Script = $ScriptPath + } + + if ($pesterModule.Version -ge '3.4.0') { + # -PesterOption was introduced before 3.4.0, and VSCodeMarker in 4.0.3-rc, + # but because no-one checks the integrity of this hashtable we can call + # all of the versions down to 3.4.0 like this + $invokePesterParams.Add("PesterOption", @{ IncludeVSCodeMarker = $true }) + } + + if ($pesterModule.Version -ge '3.4.5') { + # -Show was introduced in 3.4.5 + $invokePesterParams.Add("Show", $pester4Output) + } + + return $invokePesterParams +} + if ($All) { if ($pesterModule.Version -ge '5.0.0') { $configuration = @{ @@ -116,18 +136,9 @@ if ($All) { } Pester\Invoke-Pester -Configuration $configuration | Out-Null } - elseif ($pesterModule.Version -ge '3.4.5') { - # -Show was introduced in 3.4.5 - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -Show $pester4Output - } - elseif ($pesterModule.Version -ge '3.4.0') { - # -PesterOption was introduced before 3.4.0, and VSCodeMarker in 4.0.3-rc, - # but because no-one checks the integrity of this hashtable we can call all of the versions - # down to 3.4.0 like this - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} - } else { - Pester\Invoke-Pester -Script $ScriptPath + $invokePesterParams = Get-InvokePesterParams + Pester\Invoke-Pester @invokePesterParams } } elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { @@ -164,7 +175,8 @@ elseif ($TestName) { throw "Running tests by test name is unsafe. This should not trigger for Pester 5." } else { - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -TestName $TestName -Show $pester4Output + $invokePesterParams = Get-InvokePesterParams + Pester\Invoke-Pester @invokePesterParams } } else { @@ -177,5 +189,6 @@ else { Write-Warning "The Describe block's TestName cannot be evaluated. EXECUTING ALL TESTS instead." Write-Warning "To avoid this, install Pester >= 4.6.0 or remove any expressions in the TestName." - Pester\Invoke-Pester -Script $ScriptPath -PesterOption @{IncludeVSCodeMarker=$true} -Show $pester4Output + $invokePesterParams = Get-InvokePesterParams + Pester\Invoke-Pester @invokePesterParams } From 3ae9c99f18909389a3c0a0054d08fe9dfa1a6725 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Thu, 10 Dec 2020 17:56:53 -0800 Subject: [PATCH 7/7] Remove hardcoded output format (#3089) --- module/PowerShellEditorServices/InvokePesterStub.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/PowerShellEditorServices/InvokePesterStub.ps1 b/module/PowerShellEditorServices/InvokePesterStub.ps1 index 8f7eb94fd..6fc1e799f 100755 --- a/module/PowerShellEditorServices/InvokePesterStub.ps1 +++ b/module/PowerShellEditorServices/InvokePesterStub.ps1 @@ -130,7 +130,6 @@ if ($All) { if ($OutputPath) { $configuration.Add('TestResult', @{ Enabled = $true - OutputFormat = "NUnit2.5" OutputPath = $OutputPath }) } @@ -158,7 +157,6 @@ elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) { if ($OutputPath) { $configuration.Add('TestResult', @{ Enabled = $true - OutputFormat = "NUnit2.5" OutputPath = $OutputPath }) }