Skip to content

Import InvokePesterStub.ps1 from vscode-powershell (with history) #1513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 28, 2021
192 changes: 192 additions & 0 deletions module/PowerShellEditorServices/InvokePesterStub.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#!/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,

[Parameter()]
[switch] $MinimumVersion5,

[Parameter(Mandatory)]
[string] $Output,

[Parameter()]
[string] $OutputPath
)

$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..."
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) {
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
}
}

$pester4Output = switch ($Output) {
"None" { "None" }
"Minimal" { "Fails" }
default { "All" }
}

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 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 = @{
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 })
}

if ($OutputPath) {
$configuration.Add('TestResult', @{
Enabled = $true
OutputPath = $OutputPath
})
}
Pester\Invoke-Pester -Configuration $configuration | Out-Null
}
else {
$invokePesterParams = Get-InvokePesterParams
Pester\Invoke-Pester @invokePesterParams
}
}
elseif (($LineNumber -match '\d+') -and ($pesterModule.Version -ge '4.6.0')) {
if ($pesterModule.Version -ge '5.0.0') {
$configuration = @{
Run = @{
Path = $ScriptPath
}
Filter = @{
Line = "${ScriptPath}:$LineNumber"
}
}
if ("FromPreference" -ne $Output) {
$configuration.Add('Output', @{ Verbosity = $Output })
}

if ($OutputPath) {
$configuration.Add('TestResult', @{
Enabled = $true
OutputPath = $OutputPath
})
}

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 {
$invokePesterParams = Get-InvokePesterParams
Pester\Invoke-Pester @invokePesterParams
}
}
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."

$invokePesterParams = Get-InvokePesterParams
Pester\Invoke-Pester @invokePesterParams
}