mirror of
https://github.com/github/awesome-copilot.git
synced 2026-07-14 01:51:02 +00:00
b6a84a833b
* Refine Pester migration skill descriptions and remove release candidate notes * Take Copilot remark
222 lines
10 KiB
Markdown
222 lines
10 KiB
Markdown
# Migrating Pester v5 → v6
|
|
|
|
Pester 6 builds on v5 and is **largely backwards-compatible** — most v5 suites run on v6 with no
|
|
changes, and your existing `Should -Be` assertions keep working. The work is fixing a handful of
|
|
previously-deprecated behaviors that now throw. This is a low-to-medium effort jump.
|
|
|
|
Official guide: https://pester.dev/docs/migrations/v5-to-v6
|
|
|
|
---
|
|
|
|
## Quick upgrade checklist
|
|
|
|
For most suites this is low risk. Run through these, then read the details for anything that bites:
|
|
|
|
1. Run on **Windows PowerShell 5.1** or **PowerShell 7.4+** (older PS is dropped).
|
|
2. Check any `-ForEach`/`-TestCases` that can be empty — it now **throws** unless you add
|
|
`-AllowNullOrEmptyForEach`.
|
|
3. Remove duplicate `BeforeAll`/`BeforeEach`/`AfterAll`/`AfterEach` in the same block.
|
|
4. Replace `Assert-MockCalled` / `Assert-VerifiableMock` with `Should -Invoke` /
|
|
`Should -InvokeVerifiable`.
|
|
5. Add a default `Mock` where some calls don't match a `-ParameterFilter` — mocks no longer fall
|
|
through to the real command.
|
|
6. If you call `Invoke-Pester` with v4-style params (`-Script`, `-OutputFile`, …), switch to
|
|
`New-PesterConfiguration`.
|
|
|
|
---
|
|
|
|
## Breaking changes (symptom → fix)
|
|
|
|
### PowerShell 5.1 and 7.4+ only
|
|
PowerShell 3, 4, 6, and early/unsupported 7 are dropped (all out of support from Microsoft), which
|
|
let Pester move its C# to .NET 8 (net462 for Windows PowerShell 5.1).
|
|
|
|
- **Symptom:** Pester won't import on an older PowerShell.
|
|
- **Fix:** Update your machines and CI agents to Windows PowerShell 5.1 or PowerShell 7.4+.
|
|
|
|
### Discovery and Run now happen per file
|
|
In v5 the run had two global phases: discover **every** file, then run every file. In v6 the unit
|
|
of work is a single file — Pester discovers a file and runs it before moving to the next. This is
|
|
what enables the experimental parallel runner, and serial runs follow the same model.
|
|
|
|
- **Symptom:** a file that relied on *another* file's discovery-time side effect fails — e.g. a
|
|
module imported at the top of one file, a global variable, a changed working directory, or
|
|
`-ForEach` data defined in a different file.
|
|
- **Fix:** make each test file self-contained. Do discovery-time setup in `BeforeDiscovery`, and
|
|
import the modules the file needs in its own `BeforeAll`. For setup every file needs, use
|
|
`Run.BeforeContainer` (config) or a `Pester.BeforeContainer.ps1` at the repo root.
|
|
|
|
```powershell
|
|
BeforeDiscovery {
|
|
$cases = Get-Content "$PSScriptRoot/cases.json" | ConvertFrom-Json
|
|
}
|
|
Describe 'MyModule' {
|
|
BeforeAll { Import-Module "$PSScriptRoot/MyModule.psm1" }
|
|
It 'handles <Name>' -ForEach $cases { Invoke-Thing $Name | Should -Be 'ok' }
|
|
}
|
|
```
|
|
|
|
On-screen output also changes: one `Running tests from N files.` banner, per-file results, then a
|
|
single grand total. The old `Starting discovery in N files.` / `Discovery found X tests` framing is
|
|
gone for a normal run. The parallel runner (`Run.Parallel`) keeps the same result object with a few
|
|
edge cases — see https://pester.dev/docs/usage/result-object#parallel-runner-edge-cases.
|
|
|
|
### Empty or `$null` `-ForEach` throws
|
|
`-ForEach` (or `-TestCases`) given `$null` or `@()` now throws instead of silently skipping. This
|
|
catches the common bug of pointing `-ForEach` at a variable that wasn't defined in
|
|
`BeforeDiscovery`, or external data that failed to load.
|
|
|
|
- **Symptom:**
|
|
```
|
|
Value can not be null or empty array. If this is expected, use -AllowNullOrEmptyForEach
|
|
on this Describe, or set the Run.FailOnNullOrEmptyForEach configuration option to $false ...
|
|
```
|
|
- **Fix:** when the data can legitimately be empty, allow it on that specific block/test:
|
|
```powershell
|
|
Describe 'Optional cases' -ForEach $cases -AllowNullOrEmptyForEach {
|
|
It 'runs only when there is data' { }
|
|
}
|
|
```
|
|
You *can* disable the check for the whole run with `Run.FailOnNullOrEmptyForEach = $false`, but
|
|
that brings back the silent skipping it's meant to catch — prefer fixing the data or using
|
|
`-AllowNullOrEmptyForEach` where empty is genuinely expected.
|
|
|
|
### Duplicate setup/teardown blocks throw
|
|
A block may have only one of each `BeforeAll`/`BeforeEach`/`AfterAll`/`AfterEach`. Two of the same
|
|
(a common copy-paste bug) was silently allowed in v5; v6 throws.
|
|
|
|
- **Symptom:** `BeforeAll is already defined in this block. Each block can only have one BeforeAll.`
|
|
- **Fix:** combine them into one block:
|
|
```powershell
|
|
Describe 'd' {
|
|
BeforeAll {
|
|
$a = 1
|
|
$b = 2 # was a second BeforeAll
|
|
}
|
|
}
|
|
```
|
|
|
|
### Test names evaluate `<...>` templates as expressions
|
|
In v6 the content of every `<...>` token in a `Describe`/`Context`/`It` name is evaluated as a
|
|
PowerShell expression in the test's run scope (current `-ForEach` item and its properties, in-scope
|
|
variables, arithmetic, method calls). Everything outside `<...>` is kept literal. In v5 only simple
|
|
data/variable/property references were substituted.
|
|
|
|
- **Symptom:** a name containing expression-like content inside `<...>` that used to render
|
|
literally now evaluates.
|
|
```powershell
|
|
# v5 renders literally: "adds up to <($a + $b)>"; v6 evaluates: "adds up to 3"
|
|
It 'adds up to <($a + $b)>' -ForEach @(@{ a = 1; b = 2 }) { }
|
|
```
|
|
- **Fix (to keep the literal text):** escape the leading `<` with a backtick:
|
|
```powershell
|
|
It 'adds up to `<($a + $b)`>' -ForEach @(@{ a = 1; b = 2 }) { }
|
|
```
|
|
|
|
### `Assert-MockCalled` and `Assert-VerifiableMock` removed
|
|
Deprecated in v5, removed in v6.
|
|
|
|
- **Symptom:** `The term 'Assert-MockCalled' is not recognized ...`
|
|
- **Fix:**
|
|
```powershell
|
|
# Assert-MockCalled -> Should -Invoke
|
|
# Assert-VerifiableMock -> Should -InvokeVerifiable
|
|
Should -Invoke Get-Thing -Times 1 -Exactly
|
|
Should -InvokeVerifiable
|
|
```
|
|
|
|
### Mocks no longer fall through to the real command
|
|
In v5, a call to a mocked command that matched none of your `-ParameterFilter` mocks quietly ran
|
|
the **real** command. v6 removes that implicit fall-through.
|
|
|
|
- **Symptom:**
|
|
```
|
|
No mock for command 'Get-Thing' matched the call: none of the parameter filters matched,
|
|
and there is no default mock to fall back to. Add a default mock ...
|
|
```
|
|
- **Fix:** add a default mock (no `-ParameterFilter`) for the unfiltered calls, or widen a filter:
|
|
```powershell
|
|
Mock Get-Thing -MockWith { 'default' } # everything else
|
|
Mock Get-Thing -ParameterFilter { $Name -eq 'a' } -MockWith { 'a' } # special case
|
|
```
|
|
|
|
### `Set-ItResult -Pending` removed
|
|
`Pending` was never fully implemented in v5 and is gone.
|
|
|
|
- **Symptom:** `Parameter set cannot be resolved using the specified named parameters.`
|
|
- **Fix:** use `-Inconclusive` or `-Skipped`, or mark the test with `It … -Skip`:
|
|
```powershell
|
|
Set-ItResult -Inconclusive -Because 'not implemented yet'
|
|
```
|
|
|
|
### Code coverage uses the Profiler tracer by default
|
|
Coverage no longer sets a breakpoint on every command; it uses the Profiler's tracer, which is much
|
|
faster on large code bases. `CodeCoverage.UseBreakpoints` is no longer experimental and defaults to
|
|
`$false`.
|
|
|
|
- **Symptom:** coverage numbers differ from v5 and you want the old behavior.
|
|
- **Fix:** `$config.CodeCoverage.UseBreakpoints = $true`.
|
|
|
|
### `CodeCoverage.OutputFormat = 'CoverageGutters'` removed
|
|
All coverage output is now relative to the repo root (`Run.RepoRoot`, found from the `.git`
|
|
directory), so plain `JaCoCo` already works with the Coverage Gutters extension.
|
|
|
|
- **Symptom:** setting `OutputFormat` to `'CoverageGutters'` throws an invalid-value error.
|
|
- **Fix:** use `JaCoCo` (default) or `Cobertura`.
|
|
|
|
### `Invoke-Pester` legacy (v4) parameters removed
|
|
Only the **Simple** set (`-Path`, `-Output`, `-Container`, `-Tag`, …) and the **Advanced** set
|
|
(`-Configuration`) remain. The v4-style parameter set is gone.
|
|
|
|
- **Symptom:** calls like `Invoke-Pester -Script … -OutputFile … -OutputFormat … -EnableExit
|
|
-CodeCoverage …` fail with a parameter-binding error.
|
|
- **Fix:** use a configuration object (the full parameter→config map is in the
|
|
"`Invoke-Pester` parameters → `New-PesterConfiguration`" section of [v4-to-v5.md](v4-to-v5.md)):
|
|
```powershell
|
|
$config = New-PesterConfiguration
|
|
$config.Run.Path = './tests'
|
|
$config.Run.Exit = $true
|
|
$config.TestResult.Enabled = $true
|
|
$config.TestResult.OutputPath = 'result.xml'
|
|
$config.TestResult.OutputFormat = 'NUnitXml'
|
|
$config.CodeCoverage.Enabled = $true
|
|
$config.CodeCoverage.Path = './src'
|
|
Invoke-Pester -Configuration $config
|
|
```
|
|
|
|
> Config convenience in v6: setting **any** non-default option in the `TestResult` or
|
|
> `CodeCoverage` section auto-enables that section, so you no longer have to set `.Enabled = $true`
|
|
> separately for a report to be written.
|
|
|
|
---
|
|
|
|
## New `Should-*` assertions — optional, NOT part of upgrading
|
|
|
|
v6 adds a new family of assertions — `Should-Be`, `Should-Throw`, `Should-Invoke`, and ~40 more
|
|
(note the hyphen: `Should-Be`, a distinct command, vs. the classic `Should -Be`) — with clearer
|
|
failure messages. **You do not need to touch your existing `Should -Be` assertions to upgrade**;
|
|
they keep working. Treat any `Should -Be` → `Should-Be` rewrite as a separate, later effort, not
|
|
part of this migration. Reference: https://pester.dev/docs/commands/Should-Be.
|
|
|
|
If you do try them: the new assertions take the actual value from the pipeline or `-Actual`. The
|
|
pipeline unwraps input (so `@(1)` becomes `1`, `@()` becomes `$null`, and a collection is
|
|
re-collected as `[object[]]`, losing types like `[int[]]`). Use `-Actual` when you need the exact
|
|
value or concrete collection type.
|
|
|
|
---
|
|
|
|
## v5 → v6 checklist
|
|
|
|
- [ ] Suite runs green on v5 first (baseline).
|
|
- [ ] Running on Windows PowerShell 5.1 or PowerShell 7.4+.
|
|
- [ ] `-ForEach`/`-TestCases` that can be empty marked `-AllowNullOrEmptyForEach` (or data fixed).
|
|
- [ ] Duplicate `Before*`/`After*` blocks combined.
|
|
- [ ] `Assert-MockCalled` → `Should -Invoke`; `Assert-VerifiableMock` → `Should -InvokeVerifiable`.
|
|
- [ ] Default `Mock` added wherever calls can miss every `-ParameterFilter`.
|
|
- [ ] `Set-ItResult -Pending` → `-Inconclusive`/`-Skipped`.
|
|
- [ ] `<...>` test-name templates that should stay literal are backtick-escaped.
|
|
- [ ] Each test file is self-contained (no reliance on another file's discovery-time state).
|
|
- [ ] `Invoke-Pester` legacy params → `New-PesterConfiguration`.
|
|
- [ ] Coverage `OutputFormat` is `JaCoCo`/`Cobertura`; `UseBreakpoints` set only if old numbers needed.
|
|
- [ ] Suite green on v6; diff reviewed; committed.
|