DetentShell The PowerShell 7 ISE we should have been delivered 8 years ago*

Tutorial: generate your first Pester tests

Twenty minutes, one small function, and at the end you have a saved test file watching it. Every step shows the output to expect, from a real run of the example.

DetentShell logo
Before you start

The walkthrough uses a specific example so every step can show you what to expect. The outputs below come from running each step against the example; if you use your own function instead, the counts will differ but the shape of each step stays the same.

What you need:

01 Create the script

Press Ctrl+N for a new tab and paste this function:

function Get-DiskFreeReport {
    <#
    .SYNOPSIS
        Lists each local drive with its free-space percentage.

    .DESCRIPTION
        Checks every filesystem drive and reports how full it is, marking
        any drive whose free space has fallen below the warning threshold.

    .EXAMPLE
        Get-DiskFreeReport -WarnBelowPercent 20
    #>
    [CmdletBinding()]
    param(
        [ValidateRange(1, 99)]
        [int]$WarnBelowPercent = 15
    )

    $drives = Get-PSDrive -PSProvider FileSystem | Where-Object { $null -ne $_.Free }
    foreach ($drive in $drives) {
        $total = $drive.Used + $drive.Free
        if ($total -eq 0) { continue }
        $freePercent = [math]::Round(($drive.Free / $total) * 100, 1)
        [pscustomobject]@{
            Drive       = $drive.Name
            FreePercent = $freePercent
            LowSpace    = ($freePercent -lt $WarnBelowPercent)
        }
    }
}

Save it with Ctrl+S into a folder of its own, for example C:\Scripts\DiskTools\Get-DiskFreeReport.ps1. Saving matters here: generated tests anchor their file paths to your saved script, so tests you save later will find it.

02 Generate

Put the caret anywhere inside the function and pick Tools > Generate Pester Tests.

A new tab opens with the generated test file, and a banner sits at its top. For this function the banner reports a testability score of Medium and six placeholders. The banner’s Next placeholder button steps through them; we’ll use it in step 5.

03 Read what it wrote

Two minutes here pays off, because the file has two kinds of content and the difference is the whole idea.

Checks the generator could prove from your source are written as working assertions: the script file exists, the function is declared in it, WarnBelowPercent is an accepted parameter. These pass on their own.

Everything that depends on knowledge only you have is a skipped stub marked FILL IN. The generator saw that your function calls Get-PSDrive, so it wrote a mock for it, and it tells you plainly what that means:

# External calls inferred from the AST. Mocks return $null by default;
# define realistic return values for assertions that depend on them.
Mock Get-PSDrive { <# STUB: define return value for Get-PSDrive #> }

The assertion under that mock is guarded: while the mock returns nothing, the assertion reports itself as a pending stub instead of failing. One more detail worth noticing: there’s a change-log check that skips itself with the note that your source doesn’t use a change-log header convention. The generator asserts a convention only when your file claims one.

04 Run it untouched

Open the Pester panel (View menu, or it appears on its own when there’s something to show) and click Run these tests.

You should see: 4 passed · 0 failed · 7 skipped/pending.

That’s the honest baseline. Nothing failed, and the seven pending entries are the questions only you can answer. Pending never counts as passing here, so the tally can’t flatter you.

05 Fill one placeholder

Click Next placeholder until the caret lands on the Get-PSDrive mock, and give it a return value:

Mock Get-PSDrive { [pscustomobject]@{ Name = 'C'; Used = 60GB; Free = 40GB } }

Click Run these tests again.

You should see: 5 passed · 0 failed · 6 skipped/pending.

The assertion under the mock activated on its own. Its guard skips only while the mock returns nothing, so filling in the value was the whole job; there was no test code to edit.

06 Save it and check coverage

Click Save test. The default location is Tests\Unit\Get-DiskFreeReport.Tests.ps1 under your project root, which is where Pester projects expect test files; it asks before overwriting anything.

Click Refresh coverage and the panel lists which functions in your project have tests and which don’t. When you’re ready, Generate for all missing runs generation for the uncovered ones in a batch.

07 Run it anywhere

The saved file is ordinary Pester with no dependency on DetentShell. From any PowerShell:

Invoke-Pester .\Tests\Unit\Get-DiskFreeReport.Tests.ps1

Same file, same tally, and it behaves the same in CI.

If something doesn’t match
Where to go next

The Generating tests wiki page covers the feature per audience. Two posts in the blog series tell the longer story: one on why the generator writes FILL IN instead of guessing, and one on the panel loop from a generated file to project coverage.

Get DetentShell
PS> Start-Process "https://detentpoint.com/detentshell/download"
# Coming soon — ships once the installer is code-signed

Coming soon. DetentShell launches at $29.99 in the Microsoft Store for its first two weeks. The regular price that follows is not final yet and will be published here first; volume licensing for teams is handled separately.

Follow progress on the changelog →