This blog post is part of a series of 3 posts to learn Powershell Pester. After seeing the fundamentals of pester in part 1, we are now going to deep dive into the code and learn the details about the pester syntax. The scripts that are used through out this series are available on github here. The scripts for part two are located under the folder named part 2.
In part 3 of this series, we will tackle the advanced concepts of pester tests and talk about some of pesters features that allows us to control better the information resulting from our pester tests, such as which test failed, which one didn’t etc…

These blog posts follow each other, but can be read seperatley. The three blog posts will bring you from zero to hero in no time!

The scripts that are used through out this series about pester test are available on github here. The scripts for part one are located under the folder named part1.

In part 1 I show cased the function we are going to work with during this series, and started to introduced the very basics of Pester testing using new-Fixture. In this post, it is time for us to start some to write real pester tests ! (yay o/ ). Otherwise, how do we actually expect to learn anything, huh?

For this, I will first show the complete pester script I wrote to test the function we saw in part 1. I have tried to write the pester test in a way, so that I can showcase the most comonly used pester test options. I will highlight what the different sections brought to the game, and why we used these specific parts instead of something else. Hopefully, you will be able to write your first pester tests after reading this blog post 🙂

Pester comes with a bunch of new keywords. But not all of them will be needed to get you started. Actually, there are only a very few that you really need to know to get you started to use powershell pester. In the end,  the most used powershell pester keywords are the 5 following ones:

Describe, Context, IT, should, be

Depending on the code you are willing to test, you will need to use some other keywords, but they will probably be a replacement for the ‘be’ keyword (like not be,  or BeNullOrEmpty for instance)  these 5 keywords are the only ones you will need to write begginer to advanced pester tests.

PowerShell Pester language structure:

Pester is built on script blocks, which can be encapsulated in each other. There is an order to respect though. The following mind map shows you how the encapsulation works. (The details of the each keyword will be discussed a bit further under using a real example to make the learning process less ‘academic’).

The key words that you will be using at most at the beginning are the following ones:

Powershell pester keyword tree

 

In the image above, the keyword structure is ‘hierarchical’ simply because these keywords are actually script blocks, and should be located one in within each other. We see that a Powershell Pester script starts with a describe block, and that everthing is located in that describe block. (A context block is for exampled  located in a describe block).

If we have a look at the keywords, and read them out loud, we can already understand the logic that we can build with Pester.

Our second PowerShell Pester script

Now here is the cool part: The PowerShell Pester code!

I Have already written the pester tests for the function introduced earlier in part 1 of this series. If you look at the code, you might be able to understand the global sense of the test, and some of the concepts behind them due to the syntax which is pretty easily understandable.

It might be a lot, but please, bear with me, because I’ll explain everything that is contained in this PowerShell Pester script in detail.

The script is available on github here.

(Read through the powershell pester test quickly and meet me at the bottom of the script).

(Hey, you are back! – in case you missed it, the script from above is available on github here.)

To invoke pester, navigate to the folder where the script is located, and run invoke-pester. As explained in part 1, the invoke-pester cmdlet will search for files that end with a .tests.ps1 extension recursivley and execute each item with that extension after each other. Once invoke-pester is called, will return the following output in the console:

Powershell pester calling tests

 

All the tests passed except for one. We will come back to the failing one a bit later.

If you look at the ‘Describe Blocks’, you can Clearly see what we are exactly testing.

Main PowerShell pester commands

A powershell pester overview

Let’s go a step back and have a look to that mind map I created earlier.  I added some extra information in the image below.

Powershell pester mind map - commands tree 2

 

Actually, all the building blocks are mandatory and won’t be able to run your Powershell Pester test script, except for the context block, which can be omitted.

The image is pretty self-explanatory, but I’ll go in detail, and show case each block the next chapter below.

Describe

The Describe block is always the most upper block. In our GetComputerFileInfos.Tests.ps1 PowerShell Pester test file looks like this:

Powershell pester describe block

The describe block will contain either Context blocks (which will in their turn contain ‘IT‘ blocks) or directly ‘IT‘ block(s). The describe block is showed in the PowerShell console in Purple.

Context

A context block as it name suggests, is a block that gives additional context to your specefic test. See this for now as something purely informative.

Powershell pester it blocks

In our case, we use the Context block to englobe all our tests that will test the various possible inputs that our script can have.

Just like the Describe blocks, the pester context blocks are also showed in purple.

It

The ‘IT’ block is the heart of the PowerShell Pester test. It contains the precise element that you are testing. The ‘IT’ block contains one of the assertion operators that we will discuss in just a second. The most commonly used is the Should operator.

In our tests, the first IT block looks like this:

 

The first line we actually call is our main function Get-ComputerInfos (which is the function we actually want to test) and we put the data into the variable $Infos.

We pipe then the content of that variable to the should operator, and we specify that it should not be null or empty using the not BeNullOrEmpty operators.

If the condition is met, the test will be displayed in Green in the console. (thus the function does what it is supposed to do)

If the test is not met, it will be displayed in red in the console. (thus the function does not what it is supposed to do)

Let’s take another test, and see how that one works out:

 

In this test we can see in the ‘IT‘ block, that we are validating that when the computer name parameter is called without a value, it should not run. In the function’s logic, it will throw and error, and we want to be sure to catch that error. Having the script error out, is what we want to test.

In this particular case, when the functions throws and error that is actually something positive, and it should validate our test. The firt times I did this, it always failed the test, and there is just a small little thing to remember when doing so.

There is rule you need to remember each time you want to validate that your function threw and error: Your function call should be surround by brackets “{}” to make this actually work. If you forget to add them, the error will not be catched by PowerShell Pester, and will actually throw a real error, and make your test fail.

An example of the error you could have would be the following one:

validationMetadataException: The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

ParameterBindingValidationException: Cannot validate argument on parameter ‘computername’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

And our Powershell Pester test will actually fail, although, the test we did actually threw an error, as we wanted him to do.

Powershell pester uncatched error on throw

The thing to keep in mind, is to add our command between brackets when working with should throw, and everything should be just fine.

Read more about IT statements on the official Github wiki page here.

Should

As mentioned before, the should keyword must be located in the IT block as described in the example below.

Should be

This example counts the number of values that are sent back. This should be an object, with two rows. We verify here if the count is great then 1. If it returns $true, then we validate the test using the key word should be and adding the value it should have. In this case $true

Should not

Should not is a keyword that allows us to assert a negative value. In our case, we want to be sure, that the value that is returned from our function is null or empty

 

A list of keywords that can be used after the should operator in PowerShell Pester are the following ones:

  • Should beExactly
  • BeGreaterThan
  • BeLessthan
  • BeLike
  • BeLikeExactly
  • BeOfType
  • Exist
  • Contain
  • ContainExactly
  • Match
  • MatchExactly
  • Throw
  • BeNullOrempty

Read more about should at the official Github wiki page here.

Powershell pester scoping

Actually, the various Context Its and describe blocks are not only there to help us to display a message on the console. Each block defines it’s own scope. If we have a look at our Pester Tests again, we can see that each block has it’s own scope where each scope limits the propagation of variables through the different scopes.

The variable scoping goes as follows: Describe -> Context -> It (Context does not need to be present).
The variables are inherited from the parent scope, respecting the order described above.

Scopes are not only important for variables, but also for test drives. (A bit more about that in part 3 of this series). A test drive is created per Context block. A test drive is speceficially avaialble only in a particular scope. Therefore, understanding scopes is import. But no worries, this is pretty simple to get, as described in the image below.

Powershell Pester scoping

It is possible to have an additional scope above our describe block called InModuleScope which will allow us to tests functions located in a module. I’ll cover InModuleScope this part 3 .

Now that we have explained all the things around the PowerShell Pester syntax, let’s go back into our existing PowerShell Pester test script and have a look at that test that failed when we first launched the pester test, and try to resolve it.

A concrete pester example: how to correct a failing pester test?

Having a failing test is actually a good thing. This means that thanks to the tests you wrote, you actually found a case that was not covered by your script. This is a good thing, and that is exactly why PowerShell Pester is designed for!
This specefic error, could have been encountered by an end user in production, and could have had very negative effects on your business.

Therefore, It is always better to work a bit more ahead, and prepare for the worst, so that when you the worst actually happens, you have your belt, seat belt, airbag, parachute, kevlar, 7 wolfs and Steven Seagal ready to help.

Powershell Pester test failed - pipeline missing process block

In the screenshot above, I have invoked-Pester again. We can see that my Pipeline input doesn’t work yet :(. After a ‘quick‘ look, I noticed the ‘Process‘ block was missing in my function.

The updated and corrected function is here under (And also available on my github page here):

 

With this correction done, we can relaunch the pester tests and sure enough, everything works now as it should J

That was it for today folks. Tomorrow we will tackle our final post about this series, where we will go through the advanced technics and concepts of PowerShell Pester.

As a recall, you can find the links to the different blog post of this series: ‘Learn Powershell Pester in 3 blog posts:’

part 1

Part 2 (this blog post)

Part 3

My github repository where the scripts from this series are located