Before you run any PowerShell code you’ve developed, you better know exactly what effect it will have on your infrastructure. Pester can help you do this. Pester is an open source unit testing framework that let you create tests for validating your PowerShell scripts. It’s based on a PowerShell module authored by Scott Much and is developed and maintained on GitHub by the PowerShell community. Jeff Crosby maintains the Wiki for the framework and you can read his overview here if you’re not already familiar with Pester.
Being an author myself, I wondered whether there are any good books out there for learning about how to use Pester, and it turns out there is a really good one that was recently written by my colleague Adam Bertram. The book is titled “The Pester Book: The All in One Guide to Understanding and Writing Tests for PowerShell” and you can buy it directly from the publisher Leanpub. Adam has blogged about Pester before and how to use the framework to validate whether your PowerShell code does what you expect it to do and no more or no less, and his new book expands greatly on using Pester to act as quality assurance for your in-house developed code. And Adam certainly knows his stuff — he’s a 20-year veteran of IT and an experienced online business professional who has worked as an entrepreneur, IT influencer, Microsoft MVP, blogger, trainer, author, and content marketing writer for multiple technology companies. Adam is also the founder of the popular IT career development platform TechSnips and frequently posts articles on his site adamtheautomator.com, and you can connect with him on LinkedIn or follow him on Twitter at @adbertram. Adam graciously shared one of the chapters of his book with me and I’ve excerpted some portions of his chapter below. The chapter deals with infrastructure testing and it starts by explaining why a tool like Pester is needed by organizations that develop and use PowerShell code in their environment. The chapter begins like this:
Because Pester is a unit testing framework, some people in IT operations fail to see its benefit. They see references to mocking, testing function output, and asserting that exceptions were thrown, and automatically assume it doesn’t apply to them. They believe Pester is only about testing code. I would argue that unit testing still is essential to an IT admin who writes scripts; but beyond my unmistakable scorn for "no unit testing," there’s another kind of testing that’s possible with Pester: infrastructure validation, or infrastructure testing.
Infrastructure testing is a relatively new concept in the testing world. Since this whole DevOps movement has taken hold, a lot of IT operations people have been trying to figure out ways to adapt traditional developer concepts to infrastructure; thus, infrastructure testing was born. Infrastructure testing is a combination of the more conventional software-developer-centric integration and acceptance testing.
Infrastructure testing isn’t about testing code; it’s about testing what the code changes in the environment. Some would even argue that no code is needed at all!
Infrastructure testing is just putting a term around a practice you’ve been doing for years. Instead of only manually eyeballing the results of what your script should have changed in an environment, infrastructure testing takes the steps that you went through in your brain and converts them to code. Once those validation steps are in code, you can automate testing and inherit all of the goodness that comes with automation.
Infrastructure testing isn’t about testing code; it’s about testing what the code changes in the environment.
If you’re using code to change your infrastructure in any way, are you sure it works? I don’t mean, “It didn’t throw an error message and fill up the console with red text.” I mean, are you 100 percent confident that it did the thing you thought it should?
- Did it create that Active Directory user?
- Did it change that registry key value?
- Did it restart that virtual machine?
Scripts can be complicated and can contain lots of different ways the code can flow. One simple mistake in a single if construct could skip over entire sections of your script without you realizing it, for example. It’s essential to have an overseer to ensure that the infrastructure changes you intended to introduce are as expected. This overseer position is where Pester — and infrastructure testing — come in.
Pester is a tool that lets you write code that not only ensures that the code is written correctly but also what the code does is what you expected. How’s that done? That is what this chapter is all about.
Adam continues his chapter by providing readers with a simple example of how to leverage infrastructure testing in Pester. The example he chose to illustrate the power of Pester is a task that enterprise Windows admins often do, which is to take a batch of user account information from a CSV file or database and use PowerShell to populate this information into Active Directory. The problem of course when you do something like this is you’ll probably find a PowerShell script somewhere on the Internet and leverage or customize it to perform your task. But how do you know that the script you’re using checks for each of the attributes on each account that it processes? And does your script first check to make sure the accounts you’re adding aren’t already in Active Directory? Mistakes and omissions like these can lead to all kinds of problems including corrupting the use info you’re storing in the directory, so using a framework like Pester is essential to ensure that this kind of thing doesn’t occur.
Unfortunately, the complete walkthrough of Adam’s example including all the code and sample output is too long for us to include here in this brief article, but I can outline the steps Adam follows in his walkthrough — and you can work through the entire walkthrough and more by buying Adam’s book! Anyway, what Adam presents in his infrastructure testing walkthrough is this:
- Analyzing the code
- Getting testing dependencies in place
- Prototyping the infrastructure tests
- Assessing the current environment
- Writing the infrastructure tests
Adam then continues by highlighting the important difference between unit tests which are self-contained and don’t “touch” your production environment, and infrastructure tests that “touch” your environment, because when you perform an infrastructure test the assumptions you’ve made concerning your environment are tested by reality. And when the rubber hits the road, unexpected dependencies can be revealed. Adam then continues his infrastructure testing walkthrough by demonstrating how to perform the following tasks for his sample code:
- Building dependency discovery code
- Adding dependency checking to tests
- Creating a dependency structure
- Two ways to treat dependencies
Adam concludes with a brief look at the Operational Validation Framework (OVF) PowerShell module which uses Pester to provide a domain-specific language (DSL) specifically meant for infrastructure testing and which Adam says you can use “if you need to build infrastructure tests with Pester but don’t necessarily want to build a solution from scratch.” Adam concludes by saying, “Even though Pester wasn’t specifically designed for infrastructure testing, it can still get the job done. Since Pester is built with PowerShell and PowerShell is flexible enough to work with all kinds of infrastructure components, it only makes since Pester could do it as well. I’ve personally used Pester to test infrastructure code,” says Adam, “and as a rudimentary testing platform and can wholeheartedly recommend it.”
And having started to play around a bit with Pester myself, I too can recommend it. And I also recommend Adam’s book 🙂
Featured image: Shutterstock
More PowerShell Basics articles
- Adding custom error messages to your PowerShell scripts
- Multilingual PowerShell scripts: A must for multinational organizations
- Reading text files the easy way with PowerShell and Linux bash shell
- Managing Azure Windows Virtual Desktop using PowerShell
- Conquer the world with PowerShell global variable