Javy de Koning

Welcome

Geek 🤓, love sports 🏃‍♂️🏋️‍♂️, food 🍛,
tech , @ Amsterdam ❌❌❌.

Pester 5 scope issues and calling PSScriptAnalyzer

The latest version of Pester has some breaking changes. Variables are no longer leaking to 'it' blocks. This might break some unit-tests.

Javy de Koning

2 minute read

What is breaking in Pester 5

After the GA release of Pester 5 some of my tests started failing. You can find an overview of breaking changes on this GitHub issue as well as on the README here.

In Pester v4 the below example would work fine.

$Foo = 'Bar'

Describe "DescribeName $Foo" {
    Context "ContextName $Foo" {
        It "ItName $Foo" {
            $Foo | Should -Be 'Bar'
        }
    }
}

However, in version 5 $Foo no longer ‘leaks’ to the It block. This results in the following error:

Describing DescribeName Bar
 Context ContextName Bar
   [-] ItName Bar 10ms (7ms|2ms)
    Expected 'Bar', but got $null.

How I would run PSScriptAnalyzer tests in v4

In v4, you could just loop over the PSScriptAnalyzer rules as follows:

Describe 'PSScriptAnalyzer analysis' {
    Foreach ( $Rule in (Get-ScriptAnalyzerRule)) ) {
        It "Should not return any violation for the rule : $($Rule.RuleName)" {
            Invoke-ScriptAnalyzer -Path "..\module.psm1" -IncludeRule $Rule.RuleName |
            Should -BeNullOrEmpty
        }
    }
}

How to do it in v5

In Pester v5, we need to handle this differently. I would suggest using TestCases like so:

ModuleFolder
├── tests
|   └── PSSCriptAnalyzer.Tests.ps1
└── module-to-test.psm1

Your PSSCriptAnalyzer.Tests.ps1 would look like this:

$Modules = Get-ChildItem (Split-Path $PSScriptRoot -Parent) -Filter '*.psm1'
$Modules | ForEach-Object {
    Import-Module $_.FullName -Force
}

if ($Modules.count -gt 0) {
    Describe 'PSScriptAnalyzer analysis' {
        It "<Path> Should not violate rule: <IncludeRule>" -TestCases @(
            Foreach ($m in $Modules) {
                Foreach ($r in (Get-ScriptAnalyzerRule)) {
                    @{
                        IncludeRule = $r.RuleName
                        Path        = $m.FullName
                    }
                }
            }
        ) {
            param($IncludeRule, $Path)
            Invoke-ScriptAnalyzer -Path $Path -IncludeRule $IncludeRule |
            Should -BeNullOrEmpty
        }
    }
}

This brings along some minor issues. Today for example, you cannot access a nested hashtable in the it statement, hence you would need to always flatten the object.

comments powered by Disqus

Recent posts

Categories

About

There should go some text here but I'm to lazy to write it.