"There's no sense in being precise when you don't even know what you're talking about. -John von Neumann"

During the construction of a set of Pester tests, it can be increasingly difficult to follow the flow of each of the tests and the subjects against which these tests will be performed.

Regions to Segment Code

Since Pester tests PowerShell code, you are able to use a PowerShell featured called regions to separate sections of code. These regions allow you to collapse large sections of similar code to create an overall more pleasant script reading experience. While that may assist to some extent, it does not help you find and run specific tests.

Here's an example of what using a region would look like:

#region 'Service Tests'
describe -Name 'Important Services' {
    it 'BITS should be running' {
        $svc = Get-Servide -Name 'BITS'
        $svc.Status | should -Be 'Running'
    }
}
#endregion
Region example

This technique is only useful when reading code, but is not nearly as helpful when executing code. A region doesn't allow you to pick out precisely what test you want to run. A region simply is a way to view PowerShell code, in general. That's where using tags comes into play.

Using Pester Tags

Tags are a concept in Pester that allow you to filter describe blocks using a specific value. When you run the Invoke-Pester command to execute tests with the Tag parameter, only the describe blocks that contain the tag value specified will execute.

Here is a simple example:

describe -Name 'Important Services' -Tag 'Important' {
    it 'BITS should be running' {
        $svc = Get-Service -Name 'BITS'
        $svc.Status | should -Be 'Running'
    }
}
Tag Example

Now when you run Invoke-Pester -Path <pathhere> -Tag 'Important' you will notice behavior like below.

PS51> invoke-pester -Path C:\tests.ps1 -Tag 'NoExist'
Executing all tests in 'C:\tests.ps1' with Tags NoExist

Executing script C:\tests.ps1
Tests completed in 7ms
Tests Passed: 0, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0
PS51> invoke-pester -Path C:\tests.ps1 -Tag 'Important'
Executing all tests in 'C:\tests.ps1' with Tags Important

Executing script C:\tests.ps1

  Describing Important Services
    [-] BITS should be running 5ms
      Expected 'Running', but got Stopped.
      4:         $svc.Status | should -Be 'Running'
      at <ScriptBlock>, C:\tests.ps1: line 4
Tests completed in 106ms
Tests Passed: 0, Failed: 1, Skipped: 0, Pending: 0, Inconclusive: 0

This is useful because you do not have to have multiple test files with only one describe block in each, you could instead create a single master file with multiple describe blocks, each with their own tag.

This technique comes in handy when you have an application or infrastructure stack you want to test, and have the ability to add any new regression tests you may need in the future.

You can also use multiple tags for a describe block and provide an array of tags via Invoke-Pester. In the below example, I copied the same describe block and changed the tag from Important to NotImportant in my tests file.

PS51> invoke-pester -Path C:\tests.ps1 -Tag 'Important','NotImportant'
Executing all tests in 'C:\tests.ps1' with Tags Important', 'NotImportant

Executing script C:\tests.ps1

  Describing Important Services
    [-] BITS should be running 10ms
      Expected 'Running', but got Stopped.
      4:         $svc.Status | should -Be 'Running'
      at <ScriptBlock>, C:\tests.ps1: line 4

  Describing Important Services
    [-] BITS should be running 9ms
      Expected 'Running', but got Stopped.
      11:         $svc.Status | should -Be 'Running'
      at <ScriptBlock>, C:\tests.ps1: line 11
Tests completed in 223ms
Tests Passed: 0, Failed: 2, Skipped: 0, Pending: 0, Inconclusive: 0

How Pester has Helped Me

Since I first started learning about Pester, I have been building a few infrastructure tests for use in the environments I work in often. One particular task involves working with domain controllers and occasionally do some investigation into replication issues.

Taking what I know and turning it into some tests that run quickly and uniformly has improved my response time to domain controller issues. Tags have been extremely helpful during a couple of troubleshooting tasks now that I could target the specific failed component(s) in my test set based on results of the initial test.

There is no reason to keep running full tests for example if, for example, DNS is not working. I can then target DNS services and infrastructure without chasing other possibilities, thus wasting time. Another benefit was that I did not have to go find additional scripts because I already had the Tag parameter set for the describe block in question.

Summary

If you need a way to selectively run describe blocks in your Pester tests, check out the tags feature. Tags will help you keep your tests organized and save your sanity when you end up with thousands of tests! Trust me.

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!