Skip to content

Bump pester version to 6.1.0 - #698

Open
github-actions[bot] wants to merge 1 commit into
masterfrom
updatecli_master_4973f68e76e9827dad8a1869c9f87ad1b9ab44862fbe987e1bf1f6ad3b22805a
Open

Bump pester version to 6.1.0#698
github-actions[bot] wants to merge 1 commit into
masterfrom
updatecli_master_4973f68e76e9827dad8a1869c9f87ad1b9ab44862fbe987e1bf1f6ad3b22805a

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Bump `pester` version

Update `pester` version in build.ps1

1 file(s) updated with "PesterVersion = '6.1.0',\n": * build.ps1

6.1.0
# Pester 6.1.0

> 🙋 Want to share feedback or report a bug? Open an [issue](https://github.com/pester/Pester/issues/new/choose)
> or start a [discussion](https://github.com/pester/Pester/discussions).

The new `Should-*` assertions are now open for extension: you can write your own typed assertion
with `New-ShouldAssertion` and it behaves exactly like a built-in one. Alongside that, this release
adds two experimental features worth trying, global mocks and shuffled test order, and a large round
of assertion, output, and mocking fixes.

Pester 6 runs on **Windows PowerShell 5.1** and **PowerShell 7.4+**.

- [What's new?](#6.1.0-whats-new)
  - [Write your own `Should-*` assertions with `New-ShouldAssertion`](#6.1.0-write-your-own-should--assertions-with-new-shouldassertion)
  - [Sharper assertions](#6.1.0-sharper-assertions)
  - [Show tags in the console output](#6.1.0-show-tags-in-the-console-output)
  - [Skipped data-driven tests get real names](#6.1.0-skipped-data-driven-tests-get-real-names)
- [Experimental features](#6.1.0-experimental-features)
  - [Global mocks](#6.1.0-global-mocks)
  - [Shuffled test order](#6.1.0-shuffled-test-order)
  - [Parallel runs keep getting better](#6.1.0-parallel-runs-keep-getting-better)
- [Other improvements and fixes](#6.1.0-other-improvements-and-fixes)
- [Thank you](#6.1.0-thank-you)
- [Questions?](#6.1.0-questions)

## <a id="6.1.0-whats-new"></a>What's new?

### <a id="6.1.0-write-your-own-should--assertions-with-new-shouldassertion"></a>Write your own `Should-*` assertions with `New-ShouldAssertion`

The `Should-*` assertions in 6.0.0 were a closed set. Now you can author your own and it gets the same
building blocks a built-in assertion has: pipeline input collection, consistent value formatting, the
diagnostic hint when someone pipes a collection into a value assertion, and the shared failure path
that makes soft assertions and `-ParameterFilter` work.

You call `New-ShouldAssertion` once at the top of your function, then use the object it returns. A
passing result is implicit, you only call `Fail()` when the check does not hold, and the message
supports `<expected>`, `<actual>`, `<because>` and your own `<key>` tokens:

```powershell
function Should-BeAwesome {
    [CmdletBinding()]
    param (
        [Parameter(Position = 1, ValueFromPipeline)] $Actual,
        [Parameter(Position = 0)]                    $Expected = 'Awesome',
        [string] $Because
    )

    $assert = New-ShouldAssertion -Caller $PSCmdlet -Actual $Actual -Buffer $Input
    $Actual = $assert.Actual()

    if ($Actual -ne $Expected) {
        $assert.Fail('Expected <expected>,<because> but got <actual>.', @{ Expected = $Expected; Because = $Because })
    }
}
```

And it is used, and fails, just like a real one:

```powershell
'Awesome' | Should-BeAwesome              # passes
'meh'     | Should-BeAwesome -Because 'the docs promised' 'Awesome'
# Expected 'Awesome', because the docs promised, but got 'meh'.
```

`-As` (`Scalar` by default, or `ExactType`, `Collection`, `CollectionItems`, `None`) selects how the
piped input is collected and how the input hint is worded, so a collection assertion reads its input
as a collection just like `Should-BeCollection` does. Your custom assertion also works inside a mock
`-ParameterFilter` with no extra work.

`Fail()` also takes an optional `Hint` key in its data. It replaces the default input hint when your
assertion has something more specific to say about the failure, and is printed as `Hint: <text>` like
every other hint.

One packaging note if you ship your assertions to other people. `Should` is not an approved
PowerShell verb, so a module that exports `Should-*` functions makes `Import-Module` print the
unapproved verb warning to everyone who uses it. A manifest with an explicit `FunctionsToExport`
does not suppress it, and `-DisableNameChecking` only moves the problem to your users. Name the
function with the approved `Assert` verb and export a `Should-*` alias instead, aliases are not verb
checked:

```powershell
function Assert-BeAwesome { ... }                              # the real function

Set-Alias -Name Should-BeAwesome -Value Assert-BeAwesome
Export-ModuleMember -Function Assert-BeAwesome -Alias Should-BeAwesome
```

Nothing in Pester keys off the name of the assertion, it all keys off the `$PSCmdlet` you pass as
`-Caller`, so it behaves the same when called through the alias. A test file that defines or
dot-sources a `Should-*` function needs none of this, only modules warn.

### <a id="6.1.0-sharper-assertions"></a>Sharper assertions

The new assertion family got a round of fixes that make the messages and the parameters behave
consistently:

- **`Should-BeString -NormalizeLineEnding`** compares strings ignoring the difference between `` `n `` and
  `` `r`n ``, which is what you want when a file was written on a different platform:

  ```powershell
  "a`r`nb" | Should-BeString "a`nb" -NormalizeLineEnding   # passes
  ```

- **`Should-BeString` points its caret at the first differing character**, so a long string diff shows
  you exactly where it went wrong instead of making you count.

- **`Should-ContainCollection -IgnoreOrder`** finds the expected items in any order:

  ```powershell
  1, 2, 3 | Should-ContainCollection @(3, 1) -IgnoreOrder   # passes
  ```

- **`Should-Throw` reports the real exception type.** When an assertion inside the scriptblock throws,
  the message shows the actual exception type rather than Pester's wrapper.

- **`Should-Throw -ExceptionMessage` points at unescaped wildcards.** The message is matched with
  `-like`, so `[ ] * ?` are wildcards. When the expected and the actual message are identical except
  for those characters, the failure says so instead of showing two strings that look the same:

  ```powershell
  { throw 'value is [1]' } | Should-Throw -ExceptionMessage 'value is [1]'
  # Expected an exception, with message like 'value is [1]' to be thrown, but the message was 'value is [1]'.
  #
  # Hint: -ExceptionMessage matches using wildcards (-like). The messages are identical except for the
  # wildcard characters [ ] * ? in -ExceptionMessage. Escape them with a backtick (`[) or use
  # [System.Management.Automation.WildcardPattern]::Escape() to match them literally.
  ```

- **Type assertions honor custom `PSTypeNames`**, so an object you decorated with a synthetic type name
  asserts against that name.

- **Consistency pass:** `-Actual` sits at the same position across the assertions, `-Expected` is
  mandatory where it always should have been (`Should-NotBeString`, `Should-BeFasterThan`,
  `Should-BeSlowerThan`), `Should-Throw -Because` is named-only, and `-TrimWhitespace` is available on
  `Should-NotBeString`.

- **Formatting a complex object no longer looks like a hang.** Values that used to expand into a huge,
  slow tree (a `CommandInfo`, for example) are now summarised to something short like
  `FunctionInfo{Name=Invoke-Pester}`.

### <a id="6.1.0-show-tags-in-the-console-output"></a>Show tags in the console output

`Output.ShowTags` appends the tags of each `Describe`, `Context` and `It` to its output line, which
makes it easy to see what a `-Tag` / `-ExcludeTag` filter is actually matching:

```powershell
$config = New-PesterConfiguration
$config.Output.ShowTags = $true
# Describing Get-Planet [Tags: Slow, Unix]
```

### <a id="6.1.0-skipped-data-driven-tests-get-real-names"></a>Skipped data-driven tests get real names

A skipped data-driven test used to show the raw template, `Value <_>` repeated for every case. Now the
`<_>` and `<key>` templates are expanded from the `-ForEach` data the same way a run test expands them,
so each skipped case has a name you can actually tell apart.

```powershell
Describe 'd' {
    It 'handles <_>' -Skip -ForEach 'foo', 'bar' { }
}
# [!] handles foo
# [!] handles bar        (was: handles <_> / handles <_>)
```

## <a id="6.1.0-experimental-features"></a>Experimental features

These are on by default only when you opt in, and may still change. Try them and tell us what breaks.

### <a id="6.1.0-global-mocks"></a>Global mocks

A normal mock only applies to calls from the scope where it is defined, or from the module you name
with `-ModuleName`. To be sure a command like `Invoke-WebRequest` is never called from any code under
test, you have to know every module that might call it and mock it in each one.

Turn on the experimental `Mock.Global` option and a mock reaches the command wherever it is called,
from any module or script in the runspace:

```powershell
$config = New-PesterConfiguration
$config.Mock.Global = $true
```

You still write the mock exactly as you do today, one mock now covers every caller:

```powershell
Mock Invoke-WebRequest { '<html />' }
Get-Data                                   # a function in another module that calls Invoke-WebRequest
Should-Invoke Invoke-WebRequest -Times 1
```

A common use is making sure a command never really runs. Mock it to throw, and combine that with
`-ParameterFilter` to block only the calls you care about while the rest fall through to the real
command:

```powershell
# block deleting anything outside TestDrive, from any code under test
Mock Remove-Item { throw 'blocked' } -ParameterFilter { $Path -notlike "$TestDrive*" }
```

The mock is removed when the test or block that defined it ends, like any other mock, and it is tied
to the run that created it so it cannot leak into a nested Pester-in-Pester run. With the option on,
`-ModuleName` is only a hint used to resolve the command, not a scope, so your existing mocks keep
working unchanged.

**Please turn this on and tell us what happens.** We would like `Mock.Global` to become the default
in v7, and the feedback from this release is what decides that. For most suites we expect turning it
on to change nothing at all, the mocks already cover the calls the tests make. The one place it can
change something is a mocked command that gets called from a module you did not name with
`-ModuleName`: that call used to reach the real command, and now it gets the mock. If that changes a
result for you, or you see anything else move, please
[open an issue](https://github.com/pester/Pester/issues/new/choose). A report that says "turned it on,
nothing changed" is just as useful to us.

### <a id="6.1.0-shuffled-test-order"></a>Shuffled test order

Tests that quietly depend on running in a fixed order are a common source of "passes on my machine".
`Run.Shuffle` reorders your test files, and the blocks and tests inside them, so those hidden
dependencies surface:

```powershell
$config = New-PesterConfiguration
$config.Run.Shuffle = $true
```

Items are only reordered within their own level, a test never jumps out of its `Context`. The run
picks a seed and prints it at the start; set `Run.ShuffleSeed` to that value to replay the exact same
order:

```powershell
$config.Run.ShuffleSeed = 1234567890   # repeat a specific shuffle
```

A single file that genuinely must run in order can opt out with a comment:

```powershell
#pester:no-shuffle
Describe 'ordered steps' { ... }
```

### <a id="6.1.0-parallel-runs-keep-getting-better"></a>Parallel runs keep getting better

The experimental parallel runner from 6.0.0 got several rounds of work in 6.1.0:

- **Code coverage is collected across parallel workers**, so turning on parallel no longer means losing
  your coverage numbers.
- **`Describing` / `Context` headers render in the parallel `Detailed` output**, so the interleaved
  output is readable instead of a flat list.
- **Worker `Write-Verbose` / `Write-Debug` output is replayed interleaved with the tests** it came from.
- A **concurrent-import crash** in `Run.Parallel` (a thread-unsafe verb patch) was fixed.

## <a id="6.1.0-other-improvements-and-fixes"></a>Other improvements and fixes

- Containers that fail during discovery are now reported in the `TestResult` XML instead of vanishing.
- A stray unmatched-label `break` / `continue` fails the test instead of aborting the whole run.
- `ExcludePath` excludes directories, not just files.
- Code coverage is collected from `Invoke-InNewProcess` child processes, and a false negative for
  steppable-pipeline proxy functions was fixed.
- The JUnit `testsuite` element gets a `timestamp` attribute.
- Mocking fixes: commands with `OrderedDictionary` parameters on PowerShell 7, cmdlets with no
  `DefaultParameterSetName`, and friendlier `Encoding` parameter binding.
- The mock parameter filter serializer no longer throws when a bound parameter's `ToString()` throws;
  it fails open and keeps the diagnostic instead of taking down the test.
- `-ExpectedMessage` on `Should -Throw` now points out when the expected and actual message are
  identical except for wildcard characters, so a `[bracketed]` message no longer fails with two
  identical-looking strings.

**Full Changelog**: https://github.com/pester/Pester/compare/6.0.0...6.1.0

## <a id="6.1.0-thank-you"></a>Thank you

Thank you to everyone who filed issues, tried the alphas, and sent fixes for this release.

## <a id="6.1.0-questions"></a>Questions?

Open an [issue](https://github.com/pester/Pester/issues/new/choose) or start a
[discussion](https://github.com/pester/Pester/discussions).



🤖
GitHub Action workflow link
Updatecli logo

Created automatically by Updatecli

Options:

Most of Updatecli configuration is done via its manifest(s).

  • If you close this pull request, Updatecli will automatically reopen it, the next time it runs.
  • If you close this pull request and delete the base branch, Updatecli will automatically recreate it, erasing all previous commits made.

Feel free to report any issues at github.com/updatecli/updatecli.
If you find this tool useful, do not hesitate to star our GitHub repository as a sign of appreciation, and/or to tell us directly on our chat!

Made with ❤️️ by updatecli
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants