56 results available
Sign in
Skills directory

pester-migration

github

·

Last changed
Not yet hardened

This version isn't hardened by Chainguard

No hardening report available.


SKILL.md

Pester Migration

Pester is the test framework for PowerShell. Test files end in *.Tests.ps1 and use Describe / Context / It blocks with Should assertions. This skill upgrades an existing suite from one major Pester version to the next and gets it green again.

Detailed, symptom-driven guides live in references/ — load the one(s) for the jump you are doing.

References

ReferenceWhen to load

v3-to-v4.md

Should Be → Should -Be, Contain → FileContentMatch, Assert-VerifiableMocks → Assert-VerifiableMock, array-assertion edge cases.

v4-to-v5.md

The big one. Discovery/Run phases, BeforeAll setup, $PSScriptRoot, BeforeDiscovery, -ForEach, mock scoping, Should -Throw wildcards, Invoke-Pester → New-PesterConfiguration.

v5-to-v6.md

PowerShell 5.1/7.4+ only, per-file discovery+run, empty -ForEach throws, duplicate setup blocks throw, name <...> templates evaluate, Assert-MockCalled removed, mocks no longer fall through, code-coverage tracer, legacy Invoke-Pester params removed.

Canonical source: the official migration guides at https://pester.dev/docs/migrations/ — this skill mirrors them. When in doubt, prefer the website.

Step 0 — Detect where you are and where you're going

Find the installed version(s) and the version the tests were written for. These can differ.

# Installed Pester version(s) on this machine
Get-Module Pester -ListAvailable | Select-Object Name, Version, Path

# Version currently imported in the session
(Get-Module Pester).Version

Tell the source version from the test code with these heuristics:

You see in *.Tests.ps1 / build scriptsSuite was written for

Should Be / Should Contain (no dash)

v3 or earlier → start at v3-to-v4

$MyInvocation.MyCommand.Path + dot-source at the top of the file; arbitrary code directly under Describe

v4 → v4-to-v5

Assert-MockCalled, Assert-VerifiableMock, Set-ItResult -Pending

v4 / early-v5 (these are removed in v6)

Invoke-Pester -Script … -OutputFile … -CodeCoverage … (legacy params)

v4 invocation → map to config

BeforeAll { . $PSScriptRoot/… }, New-PesterConfiguration, Should -Invoke

already v5-style → v5-to-v6

Install the target version when ready:

# Latest stable v5 — pin the major to avoid installing Pester 6
Install-Module Pester -MaximumVersion 5.99.99 -Force

# Latest stable v6 — pin the major to avoid accidentally installing a future Pester 7
Install-Module Pester -MinimumVersion 6.0.0 -MaximumVersion 6.99.99 -Force

Migration workflow

Run this loop for each major jump. Do not jump two majors at once — go v4→v5, then v5→v6.

  1. Baseline. Run the suite on the current version first and record pass/fail. You need a known-good (or known) starting point so you can tell migration regressions apart from pre-existing failures.
    # Bare Invoke-Pester works on every major; exact parameters differ
    # (v3/v4: -Script/-OutputFile; v5+/v6: -Path/-Output).
    Invoke-Pester
  2. Read the reference for this jump (table above) so you know the full scope before editing.
  3. Edit file by file. Apply the mechanical changes (see per-jump cheat sheets below and in the reference). Keep changes small and reviewable — one file or one concern at a time.
  4. Switch versions with Install-Module (Step 0), then re-import: Remove-Module Pester; Import-Module Pester (or start a fresh session).
  5. Run and fix. Re-run with -Output Detailed; use -Output Diagnostic (v4→v5) or read the explicit v6 error messages to locate problems. Match each failure to the symptom → fix tables in the reference.
  6. Green, diff, commit. Re-run until the result matches the baseline (or better). Review the diff, then commit. Migrating in small commits makes regressions trivial to bisect.

What actually changes (scope per jump)

JumpDifficultyNature

v3 → v4

Low

Assertion-syntax rename (Should -Be). Largely script-automatable.

v4 → v5

High

New two-phase runtime. Test structure changes: setup must move into BeforeAll, discovery-time code into BeforeDiscovery, file location via $PSScriptRoot. Not a pure find-replace.

v5 → v6

Low–Medium

Backwards-compatible runtime; deprecated features now throw. Mostly small, targeted fixes. Your Should -Be assertions keep working unchanged.

Quick cheat sheets

v4 → v5 (most common fixes)

# 1. Move file import into BeforeAll, use $PSScriptRoot (NOT $MyInvocation.MyCommand.Path)
# BEFORE
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
. "$here\Get-Thing.ps1"
# AFTER
BeforeAll { . $PSScriptRoot/Get-Thing.ps1 }

# 2. Any code that DISCOVERS/generates tests must be in BeforeDiscovery
BeforeDiscovery { $cases = Get-Content $PSScriptRoot/cases.json | ConvertFrom-Json }

# 3. Should -Throw matches with -like wildcards, not .Contains
{ throw 'a long message' } | Should -Throw '*long*'

# 4. Invoke-Pester legacy params → New-PesterConfiguration (see reference for full map)

Full details, scoping rules, and the parameter→config table: references/v4-to-v5.md.

v5 → v6 (most common fixes)

# 1. Mock assertions: removed verbs — rename (old -> new):
#    Assert-MockCalled     -> Should -Invoke
#    Assert-VerifiableMock -> Should -InvokeVerifiable
Should -Invoke Get-Thing -Times 1 -Exactly
Should -InvokeVerifiable

# 2. Add a default mock — unmatched calls no longer run the real command
Mock Get-Thing { 'default' }
Mock Get-Thing -ParameterFilter { $Name -eq 'a' } -MockWith { 'a' }

# 3. Empty/$null -ForEach now throws; allow it only where empty is expected
Describe 'Optional' -ForEach $cases -AllowNullOrEmptyForEach { }

# 4. Combine duplicate BeforeAll/BeforeEach/AfterAll/AfterEach in the same block into one

Full breaking-change list with symptoms and fixes: references/v5-to-v6.md.

Safety rules

  • Tests are the spec. Migration must not change what a test asserts — only how the suite is structured and invoked. If a test starts passing/failing differently for any reason other than a documented breaking change, investigate before accepting it.
  • Automated migration scripts produce false positives. The community scripts (linked in the references) help with Should syntax and dot-sourcing, but always review the diff and re-run the suite afterward. Never bulk-edit and commit unchecked.
  • Mind file encoding when scripting replacements over *.Tests.ps1 — preserve the original encoding (UTF-8 vs ASCII) so you don't mangle non-ASCII test names.
  • Work on a branch, commit per file/concern. Small commits keep git bisect useful if a migrated test goes red later.

Install

Need this version hardened?

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream source

—

Upstream commitb6a84a833b53be54a70cea48aeab0a794f57dc74
OCI reference

—

License

MIT

Files

HARDENING.md

LICENSE

SKILL.md

references/v3-to-v4.md

references/v4-to-v5.md

references/v5-to-v6.md


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.