Skip to content

Commit 16419d0

Browse files
Upgrade Process-PSModule to Pester 6.1 (#519)
## Implemented in Process-PSModule - Enforce the Pester `[6.1.0,7.0.0)` range in reusable framework test runs. - Align module-local workflow inputs with the current Invoke-Pester contract: `Version`/`Prerelease` select Pester, while `GitHubVersion`/`GitHubPrerelease` select the GitHub module. Pester prerelease remains at the action default. - Keep the six Test-PSModule container/test files inside the action implementation at `.github/actions/Test-PSModule/src/tests`, because they are context-dependent framework suites executed against the compiled module or source tree. Discovery remains `$PSScriptRoot/tests/$settings`. - Add a framework CI contract test that validates Pester 6.1 configuration properties: - `Run.Shuffle` - `Run.ShuffleSeed` - `Run.Parallel` - `Run.ParallelThrottleLimit` - `Debug.ShowStartMarkers` - Align coverage input documentation with Pester 6.1: supported formats are JaCoCo and Cobertura, and profiler-based tracing is documented correctly. - Update Pester 6.1 authoring and coverage-report guidance. ## Pester 6.1 runtime audit A local Pester 6.1 probe generated a passing test result and coverage report, and the Get-PesterCodeCoverage action processed that JSON successfully. The coverage result shape remains compatible: `CoveragePercent`, `CoveragePercentTarget`, `CommandsMissed`, `CommandsExecuted`, `FilesAnalyzed`, and all count properties are present and consumed correctly. The Pester result still exposes `Containers`; each container retains `Data`, `Blocks`, and aggregate result/count properties. The existing container files therefore remain compatible with the compiled-module/source-tree execution model. ## Contract findings and required upstream follow-up The current `PSModule/Invoke-Pester` v5.1.0 action does not expose these Pester configuration properties as action inputs, so this repository deliberately does not add incompatible passthrough mappings: - `Run_Shuffle` - `Run_ShuffleSeed` - `Run_Parallel` - `Run_ParallelThrottleLimit` - `Debug_ShowStartMarkers` The coordinated `PSModule/Invoke-Pester` follow-up must add each input to `action.yml`, forward each `PSMODULE_INVOKE_PESTER_INPUT_*` environment variable, map them into the generated `PesterConfiguration`, and publish a version/tag that Process-PSModule can pin. Process-PSModule can then expose the corresponding reusable-action inputs and pass them through. ## Test and fixture boundaries confirmed - Module-local tests assume the built module is already loaded: `Test-ModuleLocal.yml` imports the artifact in its prescript before invoking Pester. - Framework module tests import the module explicitly in their own test scopes; no implicit preload was introduced. - PSD1 files in the repository test fixture (`src/data/Config.psd1` and `src/data/Settings.psd1`) are not implicitly loaded and are currently unused. Any future PSD1 dataset test must call `Import-PowerShellDataFile` explicitly or load it from supported setup. - `Expose-TestData` passes only explicit caller-provided fixtures as environment variables to setup, teardown, and tests. - Module linting remains a separate `Invoke-ScriptAnalyzer` job and artifact path; it is not folded into Pester execution. ## Validation - Pester 6.1 configuration contract validated locally. - Pester 6.1 result/container and coverage shapes inspected locally. - Get-PesterCodeCoverage executed against a generated Pester 6.1 coverage JSON fixture and passed. - Restored Test-PSModule scripts parsed successfully. - Test-PSModule path resolution validated from a consumer repository root. - Changed PowerShell parsed successfully. - `git diff --check` passed. Commits: `337533c`, `ad2961e`, `8c3366f`, `0423d6a` --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 7c8bc79 commit 16419d0

7 files changed

Lines changed: 48 additions & 13 deletions

File tree

.github/actions/Get-PesterCodeCoverage/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,12 @@ Summary:
7777

7878
## Requirements
7979

80-
1. **Pester Code Coverage Reports**
80+
1. **Pester 6.1 Code Coverage Reports**
81+
8182
Preceding steps must generate JSON coverage reports named `*-CodeCoverage*.json`
83+
from the Pester 6.1 `CodeCoverage` result object. The action consumes
84+
`CoveragePercent`, `CoveragePercentTarget`, `CommandsMissed`,
85+
`CommandsExecuted`, and `FilesAnalyzed` plus their count properties.
8286

8387
2. **GitHub CLI**
8488
The action uses `gh run download` to fetch artifacts from the current workflow run

.github/actions/Test-PSModule/action.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ inputs:
8585
required: false
8686
CodeCoverage_OutputFormat:
8787
description: |
88-
Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura
88+
Format to use for code coverage report. Possible values in Pester 6.1: JaCoCo or Cobertura.
8989
required: false
9090
CodeCoverage_OutputPath:
9191
description: |
@@ -113,7 +113,7 @@ inputs:
113113
required: false
114114
CodeCoverage_UseBreakpoints:
115115
description: |
116-
EXPERIMENTAL: When false, use Profiler based tracer to do CodeCoverage instead of using breakpoints.
116+
When false, use the profiler-based tracer instead of breakpoints for code coverage.
117117
required: false
118118
CodeCoverage_SingleHitBreakpoints:
119119
description: |
@@ -288,6 +288,7 @@ runs:
288288
with:
289289
Debug: ${{ inputs.Debug }}
290290
Verbose: ${{ inputs.Verbose }}
291+
Version: '[6.1.0,7.0.0)'
291292
GitHubVersion: ${{ inputs.Version }}
292293
GitHubPrerelease: ${{ inputs.Prerelease }}
293294
WorkingDirectory: ${{ inputs.WorkingDirectory }}

.github/actions/Test-PSModule/src/tests/Module/PSModule/PSModule.Tests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ if ($hasClassExporter) {
4343

4444

4545
# Run-phase setup — recompute from $Path so that It/Context blocks can use these variables.
46-
# Pester v5 Discovery and Run are separate executions. The script-scope variables above drive
46+
# Pester 6 Discovery and Run are separate executions. The script-scope variables above drive
4747
# -Skip and -ForEach during Discovery. This BeforeAll recomputes the same values for the Run
4848
# phase, where It blocks actually execute. The duplication is intentional and required.
4949
BeforeAll {

.github/workflows/Test-Actions.yml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,33 @@ jobs:
3434
- name: Install test dependencies
3535
shell: pwsh
3636
run: |
37-
Install-PSResource -Name Pester -Version '[5.7.1,6.0.0)' -Repository PSGallery -TrustRepository
37+
Install-PSResource -Name Pester -Version '[6.1.0,7.0.0)' -Repository PSGallery -TrustRepository
3838
Install-PSResource -Name PSSemVer -Repository PSGallery -TrustRepository
3939
Install-PSResource -Name GitHub -Version '[0.43.1,0.44.0)' -Repository PSGallery -TrustRepository
4040
4141
- name: Run action unit tests
4242
shell: pwsh
4343
run: |
44+
$configuration = New-PesterConfiguration
45+
$configuration.Run.Shuffle = $true
46+
$configuration.Run.ShuffleSeed = 42
47+
$configuration.Run.Parallel = $true
48+
$configuration.Run.ParallelThrottleLimit = 2
49+
$configuration.Debug.ShowStartMarkers = $true
50+
51+
$expectedOptions = @{
52+
'Run.Shuffle' = $configuration.Run.Shuffle.Value
53+
'Run.ShuffleSeed' = $configuration.Run.ShuffleSeed.Value -eq 42
54+
'Run.Parallel' = $configuration.Run.Parallel.Value
55+
'Run.ParallelThrottleLimit' = $configuration.Run.ParallelThrottleLimit.Value -eq 2
56+
'Debug.ShowStartMarkers' = $configuration.Debug.ShowStartMarkers.Value
57+
}
58+
foreach ($option in $expectedOptions.GetEnumerator()) {
59+
if (-not $option.Value) {
60+
throw "Pester 6.1 configuration option [$($option.Key)] was not applied."
61+
}
62+
}
63+
4464
$testPaths = Get-ChildItem -Path '.github/actions' -Directory |
4565
ForEach-Object { Join-Path -Path $_.FullName -ChildPath 'tests' } |
4666
Where-Object { Test-Path -Path $_ }

.github/workflows/Test-ModuleLocal.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ jobs:
7272
uses: PSModule/Invoke-Pester@4ff33199141fdf22568990b6107fe3148ae93a1c # v5.1.0
7373
with:
7474
Debug: ${{ fromJson(inputs.Settings).Debug }}
75-
Prerelease: ${{ fromJson(inputs.Settings).Prerelease }}
7675
Verbose: ${{ fromJson(inputs.Settings).Verbose }}
77-
Version: ${{ fromJson(inputs.Settings).Version }}
76+
Version: '[6.1.0,7.0.0)'
77+
GitHubVersion: ${{ fromJson(inputs.Settings).Version }}
78+
GitHubPrerelease: ${{ fromJson(inputs.Settings).Prerelease }}
7879
TestResult_TestSuiteName: ${{ matrix.TestName }}-${{ matrix.OSName }}
7980
TestResult_Enabled: true
8081
CodeCoverage_Enabled: true

docs/content/guides/writing-module-tests.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,24 @@ been built and imported.
1111

1212
## Pester version
1313

14-
Module test files declare a Pester **6.x** requirement at the top of each `*.Tests.ps1`:
14+
Module test files declare a Pester **6.1.x** requirement at the top of each `*.Tests.ps1`:
1515

1616
```powershell
17-
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.0.0'; MaximumVersion = '6.*' }
17+
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.1.0'; MaximumVersion = '6.*' }
1818
```
1919

20-
This is a convention module authors add, not something the pipeline injects. The
21-
[Invoke-Pester](https://github.com/PSModule/Invoke-Pester) action installs a matching `6.x`, so minor and patch updates
22-
flow in automatically while a new major stays a deliberate, reviewed change.
20+
This is a convention module authors add. Process-PSModule pins its reusable
21+
[Invoke-Pester](https://github.com/PSModule/Invoke-Pester) action runs to the
22+
`[6.1.0,7.0.0)` range, so patch updates flow in automatically while a new
23+
major stays a deliberate, reviewed change.
24+
25+
Pester 6.1 adds opt-in controls for shuffled and parallel file execution
26+
(`Run.Shuffle`, `Run.ShuffleSeed`, `Run.Parallel`, and
27+
`Run.ParallelThrottleLimit`) and diagnostic start markers
28+
(`Debug.ShowStartMarkers`). These controls are available when invoking Pester
29+
directly with `New-PesterConfiguration`. Process-PSModule's reusable action will
30+
expose them after the coordinated `PSModule/Invoke-Pester` action adds matching
31+
inputs; the current v5.1.0 action contract does not accept them.
2332

2433
## Test discovery
2534

docs/content/reference/powershell-module-standard.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ Process-PSModule derives `TestName` from the file's basename before the first do
319319
Each `*.Tests.ps1` file must declare the Pester 6 requirement:
320320

321321
```powershell
322-
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.0.0'; MaximumVersion = '6.*' }
322+
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.1.0'; MaximumVersion = '6.*' }
323323
```
324324

325325
Tests run against the built module artifact installed locally, across a multi-OS matrix (Linux, macOS, Windows). The full suite must also remain runnable locally without mandatory cloud resources, special access, or secrets that cannot be mocked.

0 commit comments

Comments
 (0)