Skip to main content
Version: v6 (preview) 🚧

Should

Work in progress 🛠️

This page is incomplete and will be updated as we get closer to release.

Overview

Pester includes a comprehensive set of assertions that you can use to either fail or pass a test. In fact, Pester v6 actually includes two sets of assertions:

  • All new Should-* assertions introduced in Pester v6, e.g. Should-BeString, Should-BeTrue etc.
  • The Should command known from previous version of Pester, invoked using parameter sets like Should -Be, Should -BeTrue etc.

Both types of assertions are supported side-by-side in Pester v6, but we recommend your try out and migrate to the newer assertions.

Should-* assertions (v6)

Pester v6 comes with a new set of Should-* assertions that have been built from the ground up. If you've previously tested the Assert-module, these will be familiar. Check out Command Reference in the sidebar to read more about the new assertions, e.g. Should-BeString.

These new assertions are split these categories based on their usage:

Each of these categories treats $Actual and $Expected values differently, to provide a consistent behavior when using the | syntax.

Value vs. Collection assertions

The $Actual value can be provided by two syntaxes, either by pipeline (|) or by parameter (-Actual):

1 | Should-Be -Expected 1
Should-Be -Actual 1 -Expected 1

Using pipeline syntax

When using the pipeline syntax, PowerShell unwraps the input and we lose the type of the collection on the left side. We are provided with a collection that can be either $null, empty or have items. Notably, we cannot distinguish between a single value being provided, and an array of single item:

1 | Should-Be
@(1) | Should-Be

These will both be received by the assertion as @(1). For this reason a value assertion will handle this as 1, but a collection assertion will handle this input as @(1). Another special case is @(). A value assertion will handle it as $null, but a collection assertion will handle it as @().

$null remains $null in both cases.

# Should-Be is a value assertion:
1 | Should-Be -Expected 1
@(1) | Should-Be -Expected 1
$null | Should-Be -Expected $null
@() | Should-Be -Expected $null #< --- TODO: this is not the case right now, we special case this as empty array, but is that correct? it does not play well with the value and collection assertion, and we special case it just because we can.
# $null | will give $local:input -> $null , and @() | will give $local:input -> @(), is that distinction important when we know that we will only check against values?

# This fails, because -Expected does not allow collections.
@() | Should-Be -Expected @()

```powershell
# Should-BeCollection is a collection assertion:
1 | Should-BeCollection -Expected @(1)
@(1) | Should-BeCollection -Expected @(1)
@() | Should-BeCollection -Expected @()

# This fails, because -Expected requires a collection.
$null | Should-BeCollection -Expected $null

Using the -Actual syntax

The value provides to -Actual, is always exactly the same as provided.

Should-Be -Actual 1 -Expected 1

# This fails, Actual is collection, while expected is int.
Should-Be -Actual @(1) -Expected 1

Value assertions

Generic value assertions

Generic value assertions, such as Should-Be, are for asserting on a single value. They behave quite similar to PowerShell operators, e.g. Should-Be maps to -eq.

The $Expected accepts any input that is not a collection. The type of $Expected determines the type to be used for the comparison. $Actual is automatically converted to that type.

1 | Should-Be -Expected $true
Get-Process -Name Idle | Should-Be -Expected "System.Diagnostics.Process (Idle)"

The assertions in the above examples will both pass:

  • 1 converts to bool-value as $true, which is the expected value.
  • Get-Process retrieves the Idle process (on Windows). This process object gets converted to string which is equal to the expected value.

Type specific value assertions

Type specific assertions are for asserting on a single value of a given type like boolean. These assertions take the advantage of being more specialized to provide a type specific functionality, such as Should-BeString -IgnoreWhitespace.

  • $Expected accepts input that has the same type as the assertion type. E.g. Should-BeString -Expected "my string".
  • $Actual accepts input that has the same type as the assertion type. The input is not converted to the destination type unless the assertion specifies it, e.g. Should-BeFalsy will convert to bool.

Collection assertions

TODO

Should (v4/v5)

Should is used to do an assertion that fails or passes the test.

An example of assertion is comparing two strings in case insensitive manner:

"Pester is bad." | Should -Be "Pester is awesome!"

Which throws an exception with this text to fail the test:

Expected strings to be the same, but they were different.
Expected length: 18
Actual length: 14
Strings differ at index 10.
Expected: 'Pester is awesome!'
But was: 'Pester is bad.'
----------^

Other assertion types can be found in Assertion Reference.

Collect all Should failures

Should can now be configured to continue on failure. This will report the error to Pester, but won't fail the test immediately. Instead, all the Should failures are collected and reported at the end of the test. This allows you to put multiple assertions into one It and still get complete information on failure.

This new Should behavior is opt-in and can be enabled via Should.ErrorAction = 'Continue' on the configuration object or via $PesterPreference.

 BeforeAll {
function Get-User {
@{
Name = "Jakub"
Age = 31
}
}
}

Describe "describe" {
It "user" {
$user = Get-User

$user | Should -Not -BeNullOrEmpty -ErrorAction Stop
$user.Name | Should -Be "Tomas"
$user.Age | Should -Be 27

}
}

Starting test discovery in 1 files.
Found 1 tests. 51ms
Test discovery finished. 83ms
Describing describe
[-] user 124ms (109ms|15ms)
[0] Expected strings to be the same, but they were different.
String lengths are both 5.
Strings differ at index 0.
Expected: 'Tomas'
But was: 'Jakub'
at $user.Name | Should -Be "Tomas"
[1] Expected 27, but got 31.
at $user.Age | Should -Be 27
Tests completed in 286ms
Tests Passed: 0, Failed: 1, Skipped: 0, Total: 1, NotRun: 0

This allows you to check complex objects easily without writing It for each of the properties that you want to test. You can also use -ErrorAction Stop to force a failure when a pre-condition is not met. In our case if $user was null, there would be no point in testing the object further and we would fail the test immediately.