Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Accelerate Pester Test Development

Posted on December 28, 2021December 28, 2021
pexels-thisisengineering-3862132

The other day I shared my PowerShell plans for 2022. And needless to say, I didn't wait to dig in. I am working on a new module and since it won't be published until next month, I went ahead and marked it as Core only. I also started writing a set of Pester 5.x tests for it. Naturally, this is forcing me to revisit the Pester documentation and re-learn how to construct a Pester test.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

During this process, I decided I needed to help myself speed up the test writing phase. I have a standard set of tests that I like to use for functions in my module. But copying and pasting code snippets is tedious. I know I could create a set of VS Code snippets, but that feels limiting and I'd have to make sure the snippets are available on all systems where I might be running VS Code. Instead, I wrote a PowerShell function to accelerate developing Pester 5.x tests.

My function takes a module and extracts all of the public exported functions. For each function, it creates a set of standard Pester assertions. These are the baseline or boilerplate tests that I always want to run for each function. Each function is wrapped in a Describe block. Although, I can opt for a Context block instead. This command will also insert tags. Note that my code for the tag insertion relies on the ternary operator from PowerShell 7.

$($tags ? "-tag $($tags -join ',')" : $null)

If you want to use my function in Windows PowerShell, you'll need to revise it.

The function writes strings to the pipeline.

New-PesterBlock

I can run New-PesterBlock and pipe to Out-File or Set-Clipboard.

Here's the script file with the function.

#requires -version 7.1

Function New-PesterBlock {
    <#
.SYNOPSIS
    Create a Pester 5.x test block
.DESCRIPTION
    Create a Pester test block for exported functions from a given module.
    The default output is a Describe block for each function but you can
    create a Context block as an alternative.

    The default behavior is to add a 'Function' tag to each block. You
    can specify your own comma separated list of tags. Or use a parameter
    value of $Null to not insert any tags.

    The output is written for Pester 5.x.
.EXAMPLE
    PS C:\> New-PesterBlock psteachingtools

    Describe Get-Vegetable {
    It "Should have help documentation" {
        (Get-Help Get-Vegetable).Description | Should -Not -BeNullOrEmpty
    }
    It "Should have a defined output type" {
        (Get-Command -CommandType function -name Get-Vegetable).OutputType | Should -not -BeNullOrEmpty
    }
    It "Should run without error" {
        #mock and set mandator parameters as needed
        {Get-Vegetable} | Should -Not -Throw
    } -pending

} -tag function

Describe New-Vegetable {
    It "Should have help documentation" {
        (Get-Help New-Vegetable).Description | Should -Not -BeNullOrEmpty
    }
    It "Should have a defined output type" {
        (Get-Command -CommandType function -name New-Vegetable).OutputType | Should -not -BeNullOrEmpty
    }
    It "Should run without error" {
        #mock and set mandator parameters as needed
        {New-Vegetable} | Should -Not -Throw
    } -pending

} -tag function
...

        Create a Describe block for each function in the PSTeachingTools module.
. EXAMPLE
    PS C:\> New-Pesterblock psteachingtools -BlockType Context | Set-Clipboard

    Create a context block for each function and copy the output to the Windows clipboard.
.INPUTS
    None
.OUTPUTS
    [System.String]
    #>
    [cmdletbinding()]
    [alias("npb")]
    [OutputType([System.String])]
    Param(
        [Parameter(Position = 0, Mandatory,HelpMessage = "The name of a PowerShell module.")]
        [ValidateNotNullOrEmpty()]
        [string]$ModuleName,
        [Parameter(Position = 1,HelpMessage = "What kind of Pester test block do you want to create?")]
        [ValidateSet("Describe", "Context")]
        [string]$BlockType = "Describe",
        [Parameter(HelpMessage = "Specify tags separated by commas. Use `$null to not insert any tags.")]
        [string[]]$Tag = "function"
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)"
        #Put blocktype in proper case to make it pretty
        $BlockType = [System.Globalization.CultureInfo]::CurrentUICulture.TextInfo.ToTitleCase($BlockType)
        $Tags = $tag -join ","
    } #begin

    Process {
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting commands from $ModuleName"
        Try {
            $cmds = Get-Command -Module $ModuleName -CommandType Function -ErrorAction Stop
        }
        Catch {
            Throw $_
        }
        if ($cmds) {
            Foreach ($cmd in $cmds) {
                Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Defining tests for $($cmd.name)"
                @"

$BlockType $($cmd.name) {
    It "Should have help documentation" {
        (Get-Help $($cmd.name)).Description | Should -Not -BeNullOrEmpty
    }
    It "Should have a defined output type" {
        (Get-Command -CommandType function -name $($cmd.name)).OutputType | Should -Not -BeNullOrEmpty
    }
    It "Should run without error" {
        <#
        mock and set mandatory parameters as needed
        this test is marked as pending since it
        most likely needs to be refined
        #>
        {$($cmd.name)} | Should -Not -Throw
    } -pending
    #insert additional command-specific tests

} $($tags ? "-tag $($tags -join ',')" : $null)
"@
            } #foreach cmd

        } #if cmds
        else {
            Write-Warning "No functions found in the module $Modulename or the module itself doesn't exist."
        }
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)"
    } #end

} #close New-PesterBlock

The function creates a here-string for each test block. These are my default assertions. You might want to edit your version of the function. This command is something I might integrate into a VS Code task. I hope you'll let me know how you end up using it.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

3 thoughts on “Accelerate Pester Test Development”

  1. Pingback: Accelerate Pester Test Development - The Lonely Administrator - Syndicated Blogs - IDERA Community
  2. Craig says:
    December 29, 2021 at 4:25 pm

    I wish here string were not such a wart on the nose syntax item.

  3. Pingback: Creating Boilerplate Pester Assertions – Curated SQL

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d