Skip to content

Commit fabdeb1

Browse files
Merge pull request #21 from ChrisLGardner/pester-v5-support
Pester v5 support
2 parents 31a8cb7 + 8e4ed1a commit fabdeb1

File tree

110 files changed

+506
-32
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+506
-32
lines changed

Extension/task/HelperModule.psm1 Extension/PesterTask/PesterV10/HelperModule.psm1

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function Import-Pester {
5151
}
5252

5353
if ($Version -eq "latest") {
54-
$NewestPester = Find-Module -Name Pester | Sort-Object Version -Descending | Select-Object -First 1
54+
$NewestPester = Find-Module -Name Pester -MinimumVersion 5.0.0 | Sort-Object Version -Descending | Select-Object -First 1
5555

5656
If ((Get-Module Pester -ListAvailable | Sort-Object Version -Descending| Select-Object -First 1).Version -lt $NewestPester.Version) {
5757
Install-Module -Name Pester -RequiredVersion $NewestPester.Version -Scope CurrentUser -Force -Repository $NewestPester.Repository -SkipPublisherCheck
+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
[CmdletBinding()]
2+
param
3+
(
4+
[Parameter(Mandatory)]
5+
$TestFolder,
6+
7+
[Parameter(Mandatory)]
8+
[ValidateScript( {
9+
if ((Test-Path (Split-Path $_ -Parent)) -and ($_.split('.')[-1] -eq 'xml')) {
10+
$true
11+
}
12+
else {
13+
Throw "Path is invalid or results file does not end in .xml ($_)"
14+
}
15+
})]
16+
[string]$resultsFile,
17+
18+
[string]$run32Bit,
19+
20+
[string]$additionalModulePath,
21+
22+
[string[]]$Tag,
23+
24+
[String[]]$ExcludeTag,
25+
26+
[validateScript( {
27+
if ([string]::IsNullOrWhiteSpace($_)) {
28+
$true
29+
}
30+
else {
31+
if (-not($_.Split('.')[-1] -eq 'xml')) {
32+
throw "Extension must be XML"
33+
}
34+
$true
35+
}
36+
})]
37+
[string]$CodeCoverageOutputFile,
38+
39+
[string]$CodeCoverageFolder,
40+
41+
[string]$ScriptBlock,
42+
43+
[string]$TargetPesterVersion = "latest"
44+
)
45+
46+
if ($TargetPesterVersion -match '^4') {
47+
Write-Host "##vso[task.logissue type=error]This version of the task does not support Pester V4, please use task version 9."
48+
exit 1
49+
}
50+
51+
Write-Host "TestFolder $TestFolder"
52+
Write-Host "resultsFile $resultsFile"
53+
Write-Host "run32Bit $run32Bit"
54+
Write-Host "additionalModulePath $additionalModulePath"
55+
Write-Host "tag $Tag"
56+
Write-Host "ExcludeTag $ExcludeTag"
57+
Write-Host "CodeCoverageOutputFile $CodeCoverageOutputFile"
58+
Write-Host "CodeCoverageFolder $CodeCoverageFolder"
59+
Write-Host "ScriptBlock $ScriptBlock"
60+
61+
Import-Module -Name (Join-Path $PSScriptRoot "HelperModule.psm1") -Force
62+
Import-Pester -Version $TargetPesterVersion
63+
64+
if ($run32Bit -eq $true -and $env:Processor_Architecture -ne "x86") {
65+
Write-Warning "32bit support is considered deprecated in this version of the task and will be removed in a future major version."
66+
# Get the command parameters
67+
$args = $myinvocation.BoundParameters.GetEnumerator() | ForEach-Object {
68+
if (-not([string]::IsNullOrWhiteSpace($_.Value))) {
69+
If ($_.Value -eq 'True' -and $_.Key -ne 'run32Bit' -and $_.Key -ne 'ForceUseOfPesterInTasks') {
70+
"-$($_.Key)"
71+
}
72+
else {
73+
"-$($_.Key)"
74+
"$($_.Value)"
75+
}
76+
}
77+
78+
}
79+
write-warning "Re-launching in x86 PowerShell with $($args -join ' ')"
80+
&"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" -noprofile -executionpolicy bypass -file $myinvocation.Mycommand.path $args
81+
exit
82+
}
83+
Write-Host "Running in $($env:Processor_Architecture) PowerShell"
84+
85+
if ($PSBoundParameters.ContainsKey('additionalModulePath')) {
86+
Write-Host "Adding additional module path [$additionalModulePath] to `$env:PSModulePath"
87+
$env:PSModulePath = $additionalModulePath + ';' + $env:PSModulePath
88+
}
89+
90+
$PesterConfig = @{
91+
92+
Run = @{
93+
Path = $TestFolder
94+
Exit = $true
95+
}
96+
TestResult = @{
97+
Enabled = $true
98+
OutputFormat = 'NUnit2.5'
99+
OutputPath = $resultsFile
100+
}
101+
}
102+
103+
$Filter = @{}
104+
if ($Tag) {
105+
$Tag = $Tag.Split(',').Replace('"', '').Replace("'", "")
106+
$Filter.Add('Tag', $Tag)
107+
}
108+
if ($ExcludeTag) {
109+
$ExcludeTag = $ExcludeTag.Split(',').Replace('"', '').Replace("'", "")
110+
$Filter.Add('ExcludeTag', $ExcludeTag)
111+
}
112+
113+
$PesterConfig['Filter'] = $Filter
114+
115+
$CodeCoverage = @{}
116+
if ($CodeCoverageOutputFile) {
117+
$CodeCoverage['Enabled'] = $True
118+
$CodeCoverage['OutputFormat'] = "JaCoCo"
119+
120+
if (-not $PSBoundParameters.ContainsKey('CodeCoverageFolder')) {
121+
$CodeCoverageFolder = $TestFolder
122+
}
123+
$Files = Get-ChildItem -Path $CodeCoverageFolder -include *.ps1, *.psm1 -Exclude *.Tests.ps1 -Recurse |
124+
Select-object -ExpandProperty Fullname
125+
126+
if ($Files) {
127+
$CodeCoverage.Add('Path', $Files)
128+
$CodeCoverage.Add('OutputPath', $CodeCoverageOutputFile)
129+
}
130+
else {
131+
Write-Warning -Message "No PowerShell files found under [$CodeCoverageFolder] to analyse for code coverage."
132+
}
133+
}
134+
135+
$PesterConfig['CodeCoverage'] = $CodeCoverage
136+
137+
if (-not([String]::IsNullOrWhiteSpace($ScriptBlock))) {
138+
$ScriptBlockObject = [ScriptBlock]::Create($ScriptBlock)
139+
140+
$ScriptBlockObject.Invoke()
141+
}
142+
143+
$result = Invoke-Pester -Configuration ([PesterConfiguration]$PesterConfig)
144+
145+
if ($result.failedCount -ne 0) {
146+
Write-Error "Pester returned errors"
147+
}
File renamed without changes.
+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{
2+
"id": "cca5462b-887d-4617-bf3f-dcf0d3c622e9",
3+
"name": "Pester",
4+
"friendlyName": "Pester Test Runner",
5+
"description": "Run Pester tests by either installing the latest version of Pester at run time (if possible) or using the version shipped with the task (5.0.0)",
6+
"helpMarkDown": "Version: #{Build.BuildNumber}#. [More Information](https://github.com/pester/AzureDevOpsExtension)",
7+
"category": "Test",
8+
"visibility": [
9+
"Build",
10+
"Release"
11+
],
12+
"author": "Pester",
13+
"version": {
14+
"Major": 1,
15+
"Minor": 1,
16+
"Patch": 0
17+
},
18+
"demands": [],
19+
"minimumAgentVersion": "1.82.0",
20+
"groups": [
21+
{
22+
"name": "tags",
23+
"displayName": "Tags",
24+
"isExpanded": false
25+
},
26+
{
27+
"name": "advanced",
28+
"displayName": "Advanced",
29+
"isExpanded": false
30+
}
31+
],
32+
"inputs": [
33+
{
34+
"name": "TestFolder",
35+
"aliases": [
36+
"scriptFolder"
37+
],
38+
"type": "string",
39+
"label": "Tests Folder",
40+
"defaultValue": "$(System.DefaultWorkingDirectory)\\*",
41+
"required": true,
42+
"helpMarkDown": "Folder containing tests to run from e.g $(System.DefaultWorkingDirectory)\\*"
43+
},
44+
{
45+
"name": "resultsFile",
46+
"type": "string",
47+
"label": "Results File",
48+
"defaultValue": "$(System.DefaultWorkingDirectory)\\Test-Pester.XML",
49+
"required": true,
50+
"helpMarkDown": "Results File (nUnit format)"
51+
},
52+
{
53+
"name": "CodeCoverageOutputFile",
54+
"type": "string",
55+
"label": "Code Coverage Output File",
56+
"defaultValue": "",
57+
"required": false,
58+
"helpMarkDown": "Code coverage output file (JaCoCo format) - Requires Pester version 4.0.4+"
59+
},
60+
{
61+
"name": "tag",
62+
"type": "string",
63+
"label": "Tags",
64+
"defaultValue": "",
65+
"required": false,
66+
"helpMarkDown": "Tags used to filter which tests to run.",
67+
"groupName": "tags"
68+
},
69+
{
70+
"name": "excludeTag",
71+
"type": "string",
72+
"label": "Exclude Tag",
73+
"defaultValue": "",
74+
"required": false,
75+
"helpMarkDown": "Tags to exclude when running tests.",
76+
"groupName": "tags"
77+
},
78+
{
79+
"name": "usePSCore",
80+
"type": "boolean",
81+
"label": "Use PowerShell Core (Windows Only)",
82+
"defaultValue": "False",
83+
"required": true,
84+
"helpMarkDown": "On a Windows agent, if set will run Pester tests with 'pwsh', if false will use 'PowerShell.exe'. On Non-Windows agents 'pwsh' always used",
85+
"groupName": "advanced"
86+
},
87+
{
88+
"name": "additionalModulePath",
89+
"type": "string",
90+
"label": "Path to additional PowerShell modules",
91+
"defaultValue": "",
92+
"required": false,
93+
"helpMarkDown": "Adds a path to PSModulePath before running the tests, for dependencies or generated modules",
94+
"groupName": "advanced"
95+
},
96+
{
97+
"name": "CodeCoverageFolder",
98+
"type": "string",
99+
"label": "Code Coverage Folder",
100+
"defaultValue": "",
101+
"required": false,
102+
"helpMarkDown": "Path to the folder or file to run coverage against. Requires CodeCoverageOutputFile.",
103+
"groupName": "advanced"
104+
},
105+
{
106+
"name": "run32Bit",
107+
"type": "boolean",
108+
"label": "Run in 32bit",
109+
"defaultValue": "False",
110+
"required": false,
111+
"helpMarkDown": "Run in 32bit, only applicable on Windows agents",
112+
"groupName": "advanced",
113+
"visibleRule": "usePSCore = False"
114+
},
115+
{
116+
"name": "PesterVersion",
117+
"type": "radio",
118+
"label": "Pester Version",
119+
"defaultValue": "LatestVersion",
120+
"required": false,
121+
"options": {
122+
"LatestVersion": "Latest Available version",
123+
"OtherVersion": "Specify other version"
124+
},
125+
"groupName": "advanced",
126+
"helpMarkDown": "Choose which version of Pester to use for your tests, the version specified will be downloaded from an available PS Gallery. If no gallery is available then it will fall back to the version shipped with the task, currently 4.10.1"
127+
},
128+
{
129+
"name": "TargetPesterVersion",
130+
"aliases": [
131+
"preferredPesterVersion"
132+
],
133+
"type": "string",
134+
"label": "Preferred Pester PowerShell Version",
135+
"defaultValue": "",
136+
"required": true,
137+
"visibleRule": "PesterVersion = OtherVersion",
138+
"groupName": "advanced",
139+
"helpMarkDown": "Speicify version of Pester to install if not latest. This will download it from whichever PS Gallery has it available. If it's not available then the task will fail."
140+
},
141+
{
142+
"name": "ScriptBlock",
143+
"type": "string",
144+
"label": "Pre-Test Scriptblock",
145+
"required": false,
146+
"helpMarkDown": "A scriptblock to run before tests are executed. This will be run in the scope of the task where Invoke-Pester is run.",
147+
"groupName": "advanced"
148+
}
149+
],
150+
"instanceNameFormat": "Pester Test Runner",
151+
"execution": {
152+
"Node": {
153+
"target": "pesterV10.js",
154+
"argumentFormat": ""
155+
}
156+
}
157+
}
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
function Get-HashtableFromString
2+
{
3+
param
4+
(
5+
[string]$lineInput
6+
)
7+
8+
# check for empty first
9+
If ([String]::IsNullOrEmpty($lineInput.trim(';'))) {
10+
return @{}
11+
}
12+
13+
Foreach ($line in ($lineInput -split '(?<=}\s*),')) {
14+
$Hashtable = [System.Management.Automation.Language.Parser]::ParseInput($line, [Ref]$null, [Ref]$null).Find({
15+
$args[0] -is [System.Management.Automation.Language.HashtableAst]
16+
}, $false)
17+
18+
if ($PSVersionTable.PSVersion.Major -ge 5) {
19+
# Use the language parser to safely parse the hashtable string into a real hashtable.
20+
$Hashtable.SafeGetValue()
21+
}
22+
else {
23+
Write-Warning -Message "PowerShell Version lower than 5 detected. Performing Unsafe hashtable conversion. Please update to version 5 or above when possible for safe conversion of hashtable."
24+
Invoke-Expression -Command $Hashtable.Extent
25+
}
26+
}
27+
}
28+
29+
function Import-Pester {
30+
[cmdletbinding()]
31+
param (
32+
[string]$Version
33+
)
34+
35+
36+
if ((Get-Module -Name PowerShellGet -ListAvailable) -and
37+
(Get-Command Install-Module).Parameters.ContainsKey('SkipPublisherCheck') -and
38+
(Get-PSRepository)) {
39+
40+
try {
41+
$null = Get-PackageProvider -Name NuGet -ErrorAction Stop
42+
}
43+
catch {
44+
try {
45+
Install-PackageProvider -Name Nuget -RequiredVersion 2.8.5.201 -Scope CurrentUser -Force -Confirm:$false -ErrorAction Stop
46+
}
47+
catch {
48+
Write-Host "##vso[task.logissue type=warning]Falling back to version of Pester shipped with extension. To use a newer version please update the version of PowerShellGet available on this machine."
49+
Import-Module -Name (Join-Path $PSScriptRoot "4.10.1\Pester.psd1") -Force -Verbose:$false -Global
50+
}
51+
}
52+
53+
if ($Version -eq "latest") {
54+
$NewestPester = Find-Module -Name Pester -MaximumVersion 4.99.99 | Sort-Object Version -Descending | Select-Object -First 1
55+
56+
If ((Get-Module Pester -ListAvailable | Sort-Object Version -Descending| Select-Object -First 1).Version -lt $NewestPester.Version) {
57+
Install-Module -Name Pester -RequiredVersion $NewestPester.Version -Scope CurrentUser -Force -Repository $NewestPester.Repository -SkipPublisherCheck
58+
}
59+
}
60+
else {
61+
$NewestPester = Find-Module -Name Pester -RequiredVersion $Version | Select-Object -First 1
62+
63+
Install-Module -Name Pester -RequiredVersion $NewestPester.Version -Scope CurrentUser -Force -Repository $NewestPester.Repository -SkipPublisherCheck
64+
}
65+
66+
Import-Module -Name Pester -RequiredVersion $NewestPester.Version -Verbose:$false -Global
67+
}
68+
else {
69+
Write-Host "##vso[task.logissue type=warning]Falling back to version of Pester shipped with extension. To use a newer version please update the version of PowerShellGet available on this machine."
70+
Import-Module -Name (Join-Path $PSScriptRoot "4.10.1\Pester.psd1") -Force -Verbose:$false -Global
71+
}
72+
73+
}

Extension/task/Pester.ps1 Extension/PesterTask/PesterV9/Pester.ps1

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ param
4343
[string]$TargetPesterVersion = "latest"
4444
)
4545

46+
if ($TargetPesterVersion -match '^5') {
47+
Write-Host "##vso[task.logissue type=error]This version of the task does not support Pester V5, please use task version 10 or higher."
48+
exit 1
49+
}
4650
Write-Host "scriptFolder $scriptFolder"
4751
Write-Host "resultsFile $resultsFile"
4852
Write-Host "run32Bit $run32Bit"
2.18 KB

0 commit comments

Comments
 (0)