As you begin to depend on your PowerShell scripts for more important tasks, you'll discover that building tests for those scripts become necessary.

If you're struggling with learning how to test PowerShell code or infrastructure, check out the post Write PowerShell Tests with Pester: Getting Started �for an in-depth look at writing tests with PowerShell.

If you're an IT professional and write PowerShell scripts today, you might not be familiar with the term "software testing". That's OK. Software developers and testers have been writing tests for code for decades now, but it hasn't been until recently that we IT pros started writing code that our companies depend on.

Software testing is all about writing code to verify code. Although this may sound odd, you'll see that writing tests for your code isn't a whole lot different than writing the code itself; at least not when it comes to PowerShell.

Related Podcast: What's Up With PowerShell And Pester?

For testing PowerShell code, the de facto standard is Pester. Pester is an open source project that's built as a PowerShell module that comes pre-installed with Windows 10 and Windows Server 2016. Pester can also run on older systems as well by downloading a copy from the PowerShell Gallery or downloading from Github. Pester is a project that reads specifically written test scripts and, in a nutshell, gives you a green/red output to indicate if various tests have passed.

To learn a little more about Pester and how to write tests for PowerShell, let's take a simple piece of code and write a couple of tests for it. We'll use the below script as an example:

function Do-Something {
     param(
         $String
     )
 
     if ($String -eq 1) {
         'string was not right'
     } else {
         'string was something else'
     }
 }

In the function above, I'd like to ensure that when a value of 1 is passed to $String that the function returns string was 1 and if $String is something else, the function returns string was something else. We can use Pester to make this happen.

To create a test for this, we'll first have to create another PowerShell script and make it end with Tests.ps1. Technically, this isn't necessary, but it is best practice to do so.

Pester tests are made up of scriptblocks called describe blocks and it blocks. These organize all of your tests. For example, building out a small framework of tests for our code above, it might look something like this:

describe 'Do-Something' {
 
 ��� it "when 1 is passed as String, it returns 'string was 1'" {
 
 ��� }
 
 ��� it "when anything other than 1 is passed as String, it returns 'string was something else'" {
 
 ��� }
 }

This format of placing the individual tests inside of describe blocks is how tests are built. Once you've got the basic structure built, it's then time to run the code and perform the tests.

One way to do this is to invoke the code inside of the describe block and then inside of the it blocks to assert the expected result. In this instance, I'm going to execute the function two different ways to match my tests. I'll then check to see if the output was as expected using the should keyword.

describe 'Do-Something' {
 
 ��� it "when 1 is passed as String, it returns 'string was 1'" {
 ������� Do-Something -String 1 | should be 'string was 1'
 ��� }
 
 ��� it "when anything other than 1 is passed as String, it returns 'string was something else'" {
 ������� Do-Something -String 'something else' | should be 'string was something else'
 ��� }
 }

You can see that the should keyword allows us to specify what we expect to see from the output. The should keyword can check some different values. Once you've got the test built, it then has to run. That is done through the Invoke-Pester command. This command allows you to pass your test script and to get run through the test framework. Below you can see what this looks like:

PS>; Invoke-Pester -Path C:\Do-Something.Tests.ps1
 Describing Do-Something
 � [+] when 1 is passed as String, it returns 'string was 1' 131ms
 � [+] when anything other than 1 is passed as String, it returns 'string was something else' 21ms

If I now change the code somehow and run the test again, I can get immediate feedback that something is wrong.

Describing Do-Something
 � [-] when 1 is passed as String, it returns 'string was 1' 105ms
 ��� Expected string length 12 but was 20. Strings differ at index 11.
 ��� Expected: {string was 1}
 ��� But was:� {string was not right}
 ��� ----------------------^
 ��� at line: 4 in
 ��� 4:�������� Do-Something -String 1 | should be 'string was 1'
 � [+] when anything other than 1 is passed as String, it returns 'string was something else' 24ms

Pester can perform lots of other testing tasks like testing infrastructure configuration, all kinds of various code routines and so on.

If you're interested in learning what Pester can do for you, I recommend checking out The Pester Book. This book contains everything you need to know from the ground up to get started with Pester.

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!