Safely Testing Functions from Scripts
I recently saw a post by Jakub Jares on testing self-contained scripts with Pester.
He suggests, essentially, hijacking the call to any functions, dot-sourcing the script, and then removing the hijack (an alias, in this case).
We do something similar at work to test Azure runbooks - containing all actual code that runs in a given script in an entry-point function called something similar to Start-Main
, replicating all parameters for the script, and then hijacking it for testing.
I was playing with the AST a while ago, and quite like this alternate approach:
Get-ScriptFunctions -ScriptPath "$PSScriptRoot/script1.ps1" -Export | Invoke-Expression
Describe "Get-Avocado" {
It "gets avocado" {
Get-Avocado | Should -Be 🥑
}
}
OK, so we're missing some context here - specifically, what is Get-ScriptFunctions
(other than badly named), and why do I like it more:
As you can see, it's a quick attempt to use the language parser to find all function definitions in a given file (or scriptblock) and output them - which you can pipe to Invoke-Expression
in order to import the function definitions into your current session.
I've tried to add it to a few different places, including PowerShellTemplate (where it can be used to quickly convert a monolithic function-filled PSM1/PS1 file into my preferred single-function-per-file layout). I should probably find the best / most up-to-date version and update it everywhere / put it into a small module and add dependencies, as I seem to be diverging.
Anyway, I prefer this to other approaches listed for a few reasons -
- It doesn't require you to know / list all calls in the main script
- There's no risk of unexpectedly running actual code
- You don't have to contain all run-time code in a function (and replicate huge parameter blocks)
But there's probably something I haven't considered that makes this less suitable - please let me know if I've missed something obvious!