Azure,  Powershell

Run Pester tests on Azure Pipelines

Now that I have some simple functions and some tests in my master branch on Github, I want to make sure the tests are executed (and pass!) every time I merge some new code. At this point I do not care too much about my dev branch because I know I’ll commit often and things will not always be stable, but I’ll make sure all my test will pass before I merge from dev to master (and later I way want to publish from master to the Powershell Gallery, but only if all tests pass of course!).

The first thing I need is an account on Azure DevOps (you can start with a free account) and when ready, head to Pipelines then Builds:

Azure Pipelines Builds
Azure Pipelines Builds

Since my code is in Github, that’s what I’ll choose:

Builds, Github (yaml)
Builds, Github (yaml)

The first time we setup this integration, Azure Pipelines must be authorized to access Github:

authorize azure pipelines
authorize azure pipelines
approve and install azure pipelines
approve and install azure pipelines
grant azure pipelines access
grant azure pipelines access

Since I don’t have a yaml file already, I’ll select Starter pipeline

starter pipeline
starter pipeline

At this point in my tests things got a bit murky. The Azure Devops Marketplace has (as of this post) two free extensions to run Pester tasks so I decided to try them. I installed both extensions and added them (one at a time of course šŸ˜Š) to my yaml file.

pester tasks
pester tasks

So far so good, the problem I was not able to resolve though is that it seems these extensions make assumptions on the structure of the repo and files to test and I didn’t want to change that. Admittedly I run a few tests but I did not spent hours trying to figure it out (so if anyone knows how to make those extension work, feel free to leave a comment!), my whole point was to have something quick and easy to run those tests; also, I wanted to be able to run the same command or script both on my machine and on Azure Pipelines. Well, since it’s powershell we’re talking about, why not try with a Powershell task instead? šŸ¤”

So I did and this is how my yaml file looks like:

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'windows-2019'

steps:
- task: PowerShell@2
  inputs:
    filePath: 'azure-pipelines.ps1'
    pwsh: true

- task: PublishTestResults@2
  inputs:
    testResultsFormat: 'NUnit'
    testResultsFiles: '**/TEST-*.xml'
    failTaskOnFailedTests: true

The trigger is what causes the build task to start: in my case, any merge/push operation to my master branch will do.

The task I choose is Powershell (@2 indicates this is version 2 of the Powershell Task), I want to use Powershell Core (pwsh: true) and filePath points to the script in the root folder of my repo I want to use to run Pester. I could have used an inline script here instead, but as I mentioned I want to be able to run tests the same way on my machine, so an helper script seems the best solution for the job. Finally, I want to publish the test results I’ll have Pester output as NUnit file.

Now for the helper script, I need to make sure some basic modules (Pester included šŸ¤“) are available on the VM my task will run on and if they are not, I’ll install them from the Powershell Gallery. Then I’ll simply run Invoke-Pester as I would do at the console:

"current location: $(Get-Location)"
"script root: $PSScriptRoot"
"retrieve available modules"
$modules = Get-Module -list

if ($modules.name -notcontains 'az.accounts') {
    Install-Module az.accounts -Scope CurrentUser -Force -SkipPublisherCheck
}
if ($modules.Name -notcontains 'az.resources') {
    Install-Module az.resources -scope currentuser -force -SkipPublisherCheck
}
if ($modules.Name -notcontains 'pester') {
    Install-Module -Name Pester -Force -SkipPublisherCheck
}

Invoke-Pester -Script "./Tests/" -OutputFile "./Test-Pester.XML" -OutputFormat 'NUnitXML' -CodeCoverage "./LSECosmos/*.ps1"

I can manually run ./azure-pipelines.ps1 on the console instead when I want to make sure my tests are passing before pushing to my repo or, more importantly, merge to master. Ideally the merge from dev to master should not happen unless all tests pass, but that’s a problem for another day.

Here’s what I hope to see with every merge to master šŸ¤ž:

Successful build
Successful build

The Tests tab shows the report from the NUnit file Pester created:

tests report
tests report

Finally, I can show the build status in my Github repo; I can get the status badge code from my Pipeline Build and add it to my readme.md file:

azure pipelines builds
azure pipelines builds
status badge
status badge
status badge code
status badge code
azure pipelines build status in github
azure pipelines build status in github

When everything seems to be going against you, remember that the airplane takes off against the wind, not with it. – Henry Ford 

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.