PowerShell How-To

Using PowerShell Test Case Code with Pester

When testing multiple scenarios to a single test, try this option.

Writing tests for PowerShell code can sometimes be tricky. Depending on how complex your code depends on how many tests that must be created. Also, if you've got a script or function with a lot of parameters, that piece of code can be invoked in many different ways. Since Pester scripts are created using PowerShell, this leaves a lot of flexibility in how the test scripts can be created. Because of this flexibility, accounting for all of the different ways your code can be done some different ways.

To set the stage, let's suppose you have a function with just a single parameter. Below you can see a super-simple function that has a parameter of Name that creates a text file at the root of C but only if it's a particular value.

 

function New-TextFile {
param (
[Parameter()]
[string]$Name
)
if ($Name -eq 'foo') {
New-Item -Path "C:\$Name.txt"
} else {
Write-Output 'Name is not foo'
}


}

Since the Name parameter is a string and has no parameter validation, it can be quite some things. Name could be foo, --, hhh$$$~~~~~// and so on. Apparently, a lot of these examples won't work for a file name. Best practice would dictate adding some validation to the Name parameter but let's pretend we're not doing that for now.

Because it's possible for the Name parameter to contain some different strings, I'll need to create some tests for each scenario. For this example, I'll use Pester's test cases functionality. Test cases work great when testing a function that has various input parameters. For example, in this situation, I'd like to run some tests to ensure my function follows each of the two code paths it has: when Name is foo and when it is not. These are two test cases and be setup like the following:

$testCases = @(
@{
Name = 'foo'
ExpectedObjectType = 'System.IO.FileInfo'
}
@{
Name = 'somethingelse'
ExpectedObjectType = 'string'
}
)

You can see that I have created an array called $testCases that contains two hashtables. Inside of each of these hashtables contains the parameter I'll be passing to New-TextFile as well as an expected result I'll be testing. In this case, I'm checking the object type that's returned, but this can be anything.

These test cases are fed to Pester's it block using the TestCases parameter.

 

it 'should return an object type  of <ExpectedObjectType>' -TestCases $testCases {
param($Name,$ExpectedObjectType)

New-TextFile -Name $Name | should be $ExpectedObjectType
}

Test cases do two things; it allows you to dynamically pass tokens into your it block names by enclosing the value in < and > and it also allows you to send multiple parameters to a single it block without the need for a foreach loop. When using test cases, you'll also need to include a param block for your it block as a way to pass the function parameters as well as the value you'll be testing against.

Bringing all of this code together in a describe block might look something like this:

describe 'New-TextFile' {

$testCases = @(
@{
Name = 'foo'
ExpectedObjectType = 'System.IO.FileInfo'
}
@{
Name = 'somethingelse'
ExpectedObjectType = 'string'
}
)

mock 'New-Item' {
New-MockObject -Type 'System.IO.FileInfo'
}

it 'should return an object type of <ExpectedObjectType>' -TestCases $testCases {
param($Name,$ExpectedObjectType)

New-TextFile -Name $Name | should beoftype $ExpectedObjectType
}
}

PS>
Describing New-TextFile
[+] should return an object type of System.IO.FileInfo 173ms
[+] should return an object type of string 45ms

Once you've got the framework built for test cases, adding additional cases is simple. To add a test case, I'd just add another hashtable to the $testCases array and run my test again. Since the it block will run all cases, there's no need to do anything else.

Test cases are perfect for passing different parameters to a single test and confirming a known result. Next time you have the need to pass multiple scenarios to a single test, don't use a loop. Instead, give test cases a try!

About the Author

Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.

comments powered by Disqus

SharePoint Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.