pester / Pester

Pester is the ubiquitous test and mock framework for PowerShell.
https://pester.dev/
Other
3.08k stars 470 forks source link

A positional parameter cannot be found that accepts argument '$null' when using Pester 5.1.1 #1850

Closed tbergstedt closed 3 years ago

tbergstedt commented 3 years ago

General summary of the issue

We have been using Pester v4 as a verification and validation engine within Azure DevOps Server 2020, where we execute scripts with Pester functionality to produce test results. So it isn't validation of Powershell functionality per se. When trying to run these tests using Pester v5, they seemingly wont execute at all, and the only output is an exception (see below).

Describe your environment

Pester version : 5.1.1 C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1 PowerShell version : 7.1.2 OS version : Microsoft Windows NT 10.0.18363.0

Steps to reproduce

A typical validation script is formed like this (post v5 conversion):

param (
    # Root directory for checking changed items. Use SourcesDirectory when calling from build.
    [Parameter()]
    $Directory = "$PWD"
)
BeforeAll {
    #Import common policy functions. Contains functions Get-FileEncoding and  assertion function UseFileEncoding
    Import-Module $PSScriptRoot\CommonPolicyFunctions\CommonPolicyFunctions.psd1

    # Add imported assertions to Pester. Only used to provide clearer, more readable error messages from test executions
    Add-AssertionOperator -Name 'UseFileEncoding' -Test $Function:UseFileEncoding

    # A very much simplified command than in reality. The point being that we here want to verify the encoding of an array of items.
    $changedItems = Get-ChildItem $Directory | Where-Object ...
}

Describe "VerifyFileConfiguration" {

    Context "Validating '<_>'" {
        It "'<_>' Should use correct file encoding" -Foreach $changedItems {

            $item = $(Get-Item "$i")

            $encoding = Get-FileEncoding $item
            $encoding.Encoding | Should -Not -UseFileEncoding -Encoding @("UTF-16") -item $item
        }
    }
}

-->

Expected Behavior

Pester execution of the BeforeAll clause should setup test behavior and retrieve items to test. The It clause should be executed for each file in $changedItems

Current Behavior

None of the Pester blocks are ever executed, but seems to simply be skipped. Execution ends with the output

Starting discovery in 1 files.
System.Management.Automation.ParameterBindingException: A positional parameter cannot be found that accepts argument '$null'.  
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)        
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
   at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess)
   at System.Management.Automation.PSScriptCmdlet.DoEndProcessing()
   at System.Management.Automation.CommandProcessorBase.Complete()
at <ScriptBlock>, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 2903
at Invoke-File, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 2912
at Invoke-BlockContainer, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 2837
at Discover-Test, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 1411
at Invoke-Test, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 2356
at Invoke-Pester<End>, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 4839
at <ScriptBlock>, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 8609
at Invoke-Interactively, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 8613
at Describe, C:\Users\tober\Documents\PowerShell\Modules\pester\5.1.1\Pester.psm1: line 8582
at <ScriptBlock>, C:\git\RayStation\buildtools\policies\VerifyFileConfiguration.Tests.ps1: line 90
at <ScriptBlock>, <No file>: line 1

Comment

Is execution/usage of Pester much more strict with version 5? We aren't testing any Powershell script per se, but this was fine in version 4. And I fail to see any errors in the v5 structure above. I have tried moving the -ForEach statement up to the Describe level, to no avail.

nohwnd commented 3 years ago

You are defining $changedItems in BeforeAll and use it for -ForEach, but BeforeAll executes after ForEach so the variable is not defined.

tbergstedt commented 3 years ago

Thank you for the quick reply. I understand why it went wrong, but I'm afraid I also need some guidance on how to use -ForEach with Pester 5 syntax. If I'm not to define the variable in BeforeAll, but before theIt statement, where should I define it?

fflaten commented 3 years ago

Use BeforeDiscovery to gather data to use with -Foreach. See https://pester.dev/docs/usage/data-driven-tests#beforediscovery

tbergstedt commented 3 years ago

Thanks for the quick help!