Automated Testing for your scripts – Pester | PowerShell
Tags: powershell, automatedtest, mock, pester
Published: 2022-02-16 07:09:51

---
title: Automated Testing for your scripts – Pester | PowerShell
published: true
date: 2022-02-15 18:41:05 UTC
tags: Powershell,AutomatedTest,Mock,Pester
canonical_url: 
---

 **Version:**  5.1.x

This post will be fully dedicated to how you can automate tests for your PowerShell scripts. As a scenario, you have written some new code or modified some old code and now you want to test these changes, in an automated way, before putting them in the Production environment.

**Introducing [Pester](https://github.com/pester/Pester/wiki)**

**[Pester](https://github.com/pester/Pester/wiki)** is one testing and mocking framework for PowerShell that’ll provide you with a framework for writing and running tests. Its a open source project that’s bundled with Windows 10 and later.

**What we’ll test?**

Since we are introducing this automated testing concept and we need a script to test, why not use something already created on this blog!? Therefore, we’ll test the function created during the post **[“Building a function | Powershell”](https://dev.to/toolgbrmaker/building-a-function-powershell-12d5)** (If you didn’t read it, now its a good time for it, otherwise will be hard to understand the reason of our tests).

As the first step, we need to load the Pester module and create a new text fixture to allow us test our scripts. For that we will use the following cmdlets.

```powershell
Import-Module Pester
Mkdir testOurServiceFunction
New-Fixture -Path testOurServiceFunction -Name Set-ServiceRunningStatus 
```

![](https://toolgbrmaker.files.wordpress.com/2022/02/image-4.png?w=1024)

Notice, on the above image, you should end with two PowerShell script files… One for your code and the other where you’ll built your testing conditions.

Let’s focus mainly on the **Set-ServiceRunningStatus.Tests.ps1**. Here, if you open your file, you should have something similar to the following…

```powershell
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

Describe "Set-ServiceRunningStatus" {
    It "does something useful" {
        $true | Should Be $false
    }
}
```

Explaining a bit of what you have on your test script… The first three commands are to link the test code with your code script. The next two sections are:

- **[Describe](https://github.com/pester/Pester/wiki/Describe)** – This block is designed to contain a set of tests. Since we’re introducing this automated test concept we’ll only stick with this one, but more complex are your tests, more often will be to have multiple **[Describe](https://github.com/pester/Pester/wiki/Describe)** blocks;
- **[It](https://github.com/pester/Pester/wiki/It)** – This block represents a single test where your code will either pass or fail. A **[Describe](https://github.com/pester/Pester/wiki/Describe)** block often contains many **[It](https://github.com/pester/Pester/wiki/It)** blocks.

**How we’ll test?**

First things first, we’ll start by mocking the principal “actions” from our script and are they, Restart and Start services:

```powershell
Mock Restart-Service { return 1 }
Mock Start-Service { return 1 }
```

With this, we will be able to get a counter of actions triggered and we can compare with what we are testing for the moment of our **[It](https://github.com/pester/Pester/wiki/It)** clause.

Let’s start with a basic test… Our goal will be **“accepts and restarts one running service”** and the way we will achieve it will be by using the following:

```powershell
It "accepts and restarts one running service" {
        $result = 0
        Get-Service -Name '*_W1*' | Where-Object { if ($_.Status -eq 'Running') { $result += 1 } }
        Set-ServiceRunningStatus -Name '*_W1*' 
        Assert-MockCalled Restart-Service -Exactly $result -Scope It
}
```

On the above test, we are looking for a restart on running services with Name that includes **\_W1** string and counting the ones that will be impacted. After that, we will invoke our function and check with the **[Assert-MockCalled](https://pester-docs.netlify.app/docs/commands/Assert-MockCalled)** if the number of restart are coincident with the number of Running Services with name that includes **\_W1**.

Let’s execute and see the results so far…

![](https://toolgbrmaker.files.wordpress.com/2022/02/image-5.png?w=1024)

Well, so far so good, 1 out of 1 passed. But how much, quantitively, I’ve covered in my script with the last test!?

Let’s see by using the parameter -CodeCoverage.

```powershell
invoke-pester -CodeCoverage .\Set-ServiceRunningStatus.ps1
```

![](https://toolgbrmaker.files.wordpress.com/2022/02/image-7.png?w=1024)

We have half of the script, tested. As you can see, besides having the covered percentage we have also the missed commands so far. Let’s give it a try to add more tests and try to cover more amount of the script.

```powershell
    It "accepts and restarts multiple running services" {
        $result = 0
        Get-Service -Name '*Pharma*' | Where-Object { if ($_.Status -eq 'Running') { $result += 1 } }
        Set-ServiceRunningStatus -Name '*Pharma*' 
        Assert-MockCalled Restart-Service -Exactly $result -Scope It
    }

    It "accepts and restarts one running service" {
        $result = 0
        Get-Service -Name '*_W1*' | Where-Object { if ($_.Status -eq 'Running') { $result += 1 } }
        Set-ServiceRunningStatus -Name '*_W1*' -Force
        Assert-MockCalled Restart-Service -Exactly $result -Scope It
    } 

    It "accepts and restarts one running service on a Computer" {
        $result = 0
        Get-Service -ComputerName 'PTPOPF247203' -Name '*_W1*' | Where-Object { if ($_.Status -eq 'Running') { $result += 1 } }
        Set-ServiceRunningStatus -ComputerName 'PTPOPF247203' -Name '*_W1*'
        Assert-MockCalled Restart-Service -Exactly $result -Scope It
    } 
```

With a few more, like the above ones, we have been able to achieve the following coverage:

![](https://toolgbrmaker.files.wordpress.com/2022/02/image-8.png?w=1024)

And that’s it. Lightly we have been able to see how to test our PowerShell scripts and automate this annoying task… At least for me, it is an annoying one.

We have also been able to see a metric of the code covered by our tests and have a guide of how to achieve better tests and inherently, better solutions with this testing framework.

**Note:** Besides internet references, I’ve also used the learning concepts acquired in the following **[book](https://www.amazon.com/gp/product/1617295094/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1617295094&linkCode=as2&tag=toolgbrmaker2-20&linkId=afa15f19fc0419a6851496e32f39b370)**. I advise it as good reading.

Stay safe!