Pester Should migration
Convert classic space-separated Pester assertions such as Should -Be to the Pester v6 command form such as Should-Be, using behavior-aware mappings instead of blind text replacement.
When to invoke
- "Convert these Pester assertions to Should-* syntax."
- "Migrate
Should -Be to Pester v6 style."
- "Rewrite
Should -Not -Be calls in these .Tests.ps1 files."
- "Modernize Pester v5 assertions without changing test behavior."
- "Enable
Should.DisableV5 after converting assertions."
Inputs
Use $ARGUMENTS as the file, folder, or suite scope to migrate. If $ARGUMENTS is empty, inspect the user's selected context or ask for a target before editing. Limit changes to PowerShell files, especially *.Tests.ps1 and relevant .ps1 helpers.
Prerequisites and context
- Requires Pester v6+ for the new
Should-* commands.
- The classic
Should -Be style still works in v6, so migration is optional and incremental.
- Verified guidance originated against Pester 6.0.0-rc2; confirm current command behavior when exact semantics matter.
- Use the companion
pester-migration skill when the suite also needs runtime, mock, or config migration across v3→v4→v5→v6.
Progressive disclosure and bundled resources
references/assertion-map.md: full operator-by-operator conversion table with before/after examples and workarounds.
Load it for any operator not listed in the quick mapping or when a behavioral gotcha applies.
Conversion map
| Classic v5 |
New v6 |
$x | Should -Be 1 |
$x | Should-Be 1 |
$x | Should -Not -Be 1 |
$x | Should-NotBe 1 |
$x | Should -BeExactly 'A' |
$x | Should-BeString 'A' -CaseSensitive |
$x | Should -BeGreaterOrEqual 2 |
$x | Should-BeGreaterThanOrEqual 2 |
$x | Should -BeLessOrEqual 2 |
$x | Should-BeLessThanOrEqual 2 |
$x | Should -BeLike 'a*' |
$x | Should-BeLikeString 'a*' |
$x | Should -Match 're' |
$x | Should-MatchString 're' |
$x | Should -BeOfType [int] |
$x | Should-HaveType ([int]) |
$x | Should -BeNullOrEmpty |
Choose Should-BeNull, Should-BeEmptyString, Should-BeCollection -Count 0, or Should-BeFalsy. |
$c | Should -HaveCount 3 |
$c | Should-BeCollection -Count 3 |
$c | Should -Contain 2 |
$c | Should-ContainCollection 2 |
{ ... } | Should -Throw 'msg' |
{ ... } | Should-Throw -ExceptionMessage 'msg' |
Should -Invoke Get-Thing |
Should-Invoke Get-Thing |
Should -InvokeVerifiable |
Should-Invoke -Verifiable |
Assert-MockCalled |
Should-Invoke when also completing broader v6 mock migration. |
Procedure
- Search only the requested scope for
Should -, Should -Not -, and Assert-MockCalled in *.Tests.ps1 and .ps1 files.
- Apply mechanical mappings only where the operator has identical behavior.
- Stop and choose by intent for case sensitivity, truthiness, null-or-empty, collections, pipeline unwrapping,
Should -Exist, file-content assertions, and Should -BeIn.
- Run
Invoke-Pester -Path ./tests or the smallest equivalent suite command.
- If the suite is fully migrated and the user wants enforcement, set:
$config = New-PesterConfiguration
$config.Should.DisableV5 = $true
Behavioral gotchas
| Gotcha |
Rule |
| Case sensitivity |
Should -Be is case-insensitive; Should -BeExactly requires Should-BeString -CaseSensitive. Also map BeLikeExactly to Should-BeLikeString -CaseSensitive and MatchExactly to Should-MatchString -CaseSensitive. |
| Truthy/falsy |
Classic Should -BeTrue and Should -BeFalse accept truthy/falsy values. New Should-BeTrue and Should-BeFalse are strict booleans; use Should-BeTruthy or Should-BeFalsy to preserve loose behavior. |
| Null or empty |
BeNullOrEmpty has no single equivalent. Pick null, empty string, empty collection, whitespace, or falsy by test intent. |
| Collections |
New Should-Be is a value assertion and errors when -Expected is a collection. Use Should-BeCollection for arrays and exact collection equality. |
| Pipeline unwrapping |
Pipeline input unwraps @(1) to 1, @() to $null, and re-collects typed arrays as [object[]]. Use -Actual when exact value or concrete type matters. |
| Missing equivalents |
Should -Exist and Should -FileContentMatch* have no new counterpart. Keep classic form or rewrite with Test-Path and Get-Content -Raw. |
| BeIn direction |
There is no Should-BeIn; reverse operands with Should-ContainCollection or keep the classic form. |
Compatibility terminology
Preserve these baseline terms when they appear in user input, existing files, logs, or migration output; they are included to keep legacy wording, commands, paths, and API names recognizable during execution.
->
and
as
$collection | Should-ContainCollection $value
$false
$null
$true
$value | Should -BeIn $collection
$x | Should-Be 1
(Get-Content $p -Raw) | Should-MatchString 're'
). The new
*.ps1
, and a typed collection (
-Actual
-BeFalse
-Because
-Not
1, 2, 3 | Should-ContainCollection @(1, 2)
Should
Should -*
Should -Contain
Should -Not -BeNullOrEmpty
Should-Be -Actual $x -Expected 1
Should-HaveType
Should-NotBe
Should-NotBeEmptyString
Should-NotBeNull
Should-NotBeWhiteSpaceString
Test-Path $p | Should-BeTrue
[object[]]
actual/expected
case-sensitive
https://pester.dev/docs/assertions/should-command
https://pester.dev/docs/commands/Should-Be
https://pester.dev/docs/migrations/v5-to-v6
re-check
re-collected
single-item
step-3--check-the-behavioral-gotchas-do-not-skip
type-aware
whole-collection
Output template
## Pester Should migration result
**Status:** complete | needs human decision | blocked
**Scope:** `$ARGUMENTS`
### Assertion changes
| File | Converted | Left classic | Reason |
| --- | ---: | ---: | --- |
| `<file>.Tests.ps1` | <count> | <count> | <Should -Exist, BeNullOrEmpty decision, or none> |
### Validation
- `Invoke-Pester -Path ./tests`: <pass/fail/not run>
### Human decisions
- <truthy/falsy, null-or-empty, collection, or direction choice>
Quality gate
References
1---2name: pester-should-migration-23description: Convert classic Pester v5 `Should -...` assertions to Pester v6 `Should-*` assertion commands while preserving behavior. Use when asked to migrate, convert, rewrite, or modernize `Should -Be`, `Should -Not -Be`, `Should -Throw`, `Should -Invoke`, or other assertions in .Tests.ps1 and PowerShell files.4---56# Pester Should migration78Convert classic space-separated Pester assertions such as `Should -Be` to the Pester v6 command form such as `Should-Be`, using behavior-aware mappings instead of blind text replacement.910## When to invoke1112- "Convert these Pester assertions to Should-* syntax."13- "Migrate `Should -Be` to Pester v6 style."14- "Rewrite `Should -Not -Be` calls in these .Tests.ps1 files."15- "Modernize Pester v5 assertions without changing test behavior."16- "Enable `Should.DisableV5` after converting assertions."1718## Inputs1920Use `$ARGUMENTS` as the file, folder, or suite scope to migrate. If `$ARGUMENTS` is empty, inspect the user's selected context or ask for a target before editing. Limit changes to PowerShell files, especially `*.Tests.ps1` and relevant `.ps1` helpers.2122## Prerequisites and context2324- Requires Pester v6+ for the new `Should-*` commands.25- The classic `Should -Be` style still works in v6, so migration is optional and incremental.26- Verified guidance originated against Pester 6.0.0-rc2; confirm current command behavior when exact semantics matter.27- Use the companion `pester-migration` skill when the suite also needs runtime, mock, or config migration across v3→v4→v5→v6.2829## Progressive disclosure and bundled resources3031- `references/assertion-map.md`: full operator-by-operator conversion table with before/after examples and workarounds.3233Load it for any operator not listed in the quick mapping or when a behavioral gotcha applies.3435## Conversion map3637| Classic v5 | New v6 |38| --- | --- |39| `$x \| Should -Be 1` | `$x \| Should-Be 1` |40| `$x \| Should -Not -Be 1` | `$x \| Should-NotBe 1` |41| `$x \| Should -BeExactly 'A'` | `$x \| Should-BeString 'A' -CaseSensitive` |42| `$x \| Should -BeGreaterOrEqual 2` | `$x \| Should-BeGreaterThanOrEqual 2` |43| `$x \| Should -BeLessOrEqual 2` | `$x \| Should-BeLessThanOrEqual 2` |44| `$x \| Should -BeLike 'a*'` | `$x \| Should-BeLikeString 'a*'` |45| `$x \| Should -Match 're'` | `$x \| Should-MatchString 're'` |46| `$x \| Should -BeOfType [int]` | `$x \| Should-HaveType ([int])` |47| `$x \| Should -BeNullOrEmpty` | Choose `Should-BeNull`, `Should-BeEmptyString`, `Should-BeCollection -Count 0`, or `Should-BeFalsy`. |48| `$c \| Should -HaveCount 3` | `$c \| Should-BeCollection -Count 3` |49| `$c \| Should -Contain 2` | `$c \| Should-ContainCollection 2` |50| `{ ... } \| Should -Throw 'msg'` | `{ ... } \| Should-Throw -ExceptionMessage 'msg'` |51| `Should -Invoke Get-Thing` | `Should-Invoke Get-Thing` |52| `Should -InvokeVerifiable` | `Should-Invoke -Verifiable` |53| `Assert-MockCalled` | `Should-Invoke` when also completing broader v6 mock migration. |5455## Procedure56571. Search only the requested scope for `Should -`, `Should -Not -`, and `Assert-MockCalled` in `*.Tests.ps1` and `.ps1` files.582. Apply mechanical mappings only where the operator has identical behavior.593. Stop and choose by intent for case sensitivity, truthiness, null-or-empty, collections, pipeline unwrapping, `Should -Exist`, file-content assertions, and `Should -BeIn`.604. Run `Invoke-Pester -Path ./tests` or the smallest equivalent suite command.615. If the suite is fully migrated and the user wants enforcement, set:6263```powershell64$config = New-PesterConfiguration65$config.Should.DisableV5 = $true66```6768## Behavioral gotchas6970| Gotcha | Rule |71| --- | --- |72| Case sensitivity | `Should -Be` is case-insensitive; `Should -BeExactly` requires `Should-BeString -CaseSensitive`. Also map `BeLikeExactly` to `Should-BeLikeString -CaseSensitive` and `MatchExactly` to `Should-MatchString -CaseSensitive`. |73| Truthy/falsy | Classic `Should -BeTrue` and `Should -BeFalse` accept truthy/falsy values. New `Should-BeTrue` and `Should-BeFalse` are strict booleans; use `Should-BeTruthy` or `Should-BeFalsy` to preserve loose behavior. |74| Null or empty | `BeNullOrEmpty` has no single equivalent. Pick null, empty string, empty collection, whitespace, or falsy by test intent. |75| Collections | New `Should-Be` is a value assertion and errors when `-Expected` is a collection. Use `Should-BeCollection` for arrays and exact collection equality. |76| Pipeline unwrapping | Pipeline input unwraps `@(1)` to `1`, `@()` to `$null`, and re-collects typed arrays as `[object[]]`. Use `-Actual` when exact value or concrete type matters. |77| Missing equivalents | `Should -Exist` and `Should -FileContentMatch*` have no new counterpart. Keep classic form or rewrite with `Test-Path` and `Get-Content -Raw`. |78| BeIn direction | There is no `Should-BeIn`; reverse operands with `Should-ContainCollection` or keep the classic form. |7980## Compatibility terminology8182Preserve these baseline terms when they appear in user input, existing files, logs, or migration output; they are included to keep legacy wording, commands, paths, and API names recognizable during execution.8384- ` -> `85- ` and `86- ` as `87- `$collection | Should-ContainCollection $value`88- `$false`89- `$null`90- `$true`91- `$value | Should -BeIn $collection`92- `$x | Should-Be 1`93- `(Get-Content $p -Raw) | Should-MatchString 're'`94- `). The new `95- `*.ps1`96- `, and a typed collection (`97- `-Actual`98- `-BeFalse`99- `-Because`100- `-Not`101- `1, 2, 3 | Should-ContainCollection @(1, 2)`102- `Should`103- `Should -*`104- `Should -Contain`105- `Should -Not -BeNullOrEmpty`106- `Should-Be -Actual $x -Expected 1`107- `Should-HaveType`108- `Should-NotBe`109- `Should-NotBeEmptyString`110- `Should-NotBeNull`111- `Should-NotBeWhiteSpaceString`112- `Test-Path $p | Should-BeTrue`113- `[object[]]`114- `actual/expected`115- `case-sensitive`116- `https://pester.dev/docs/assertions/should-command`117- `https://pester.dev/docs/commands/Should-Be`118- `https://pester.dev/docs/migrations/v5-to-v6`119- `re-check`120- `re-collected`121- `single-item`122- `step-3--check-the-behavioral-gotchas-do-not-skip`123- `type-aware`124- `whole-collection`125126## Output template127128```markdown129## Pester Should migration result130131**Status:** complete | needs human decision | blocked132**Scope:** `$ARGUMENTS`133134### Assertion changes135| File | Converted | Left classic | Reason |136| --- | ---: | ---: | --- |137| `<file>.Tests.ps1` | <count> | <count> | <Should -Exist, BeNullOrEmpty decision, or none> |138139### Validation140- `Invoke-Pester -Path ./tests`: <pass/fail/not run>141142### Human decisions143- <truthy/falsy, null-or-empty, collection, or direction choice>144```145146## Quality gate147148- [ ] `$ARGUMENTS` or selected scope was consumed and limited to PowerShell test targets.149- [ ] `references/assertion-map.md` was used for non-trivial operators.150- [ ] No behavioral gotcha was converted by blind rename.151- [ ] `Should -Exist` and `Should -FileContentMatch*` were kept or rewritten intentionally.152- [ ] `Invoke-Pester` or the suite's existing test command was run after changes.153- [ ] Any `Should.DisableV5` enforcement happened only after remaining classic assertions were addressed.154155## References156157- [Should-Be command](https://pester.dev/docs/commands/Should-Be)158- [Should assertions concept](https://pester.dev/docs/assertions/should-command)159- [Pester v5 to v6 migration](https://pester.dev/docs/migrations/v5-to-v6)