Thursday, 18 February 2021
Pester is a PowerShell based test framework which makes it very simple to write integration tests. This article gives and overview and some usefull resources.
This article was published at GitHub. It is open source and you can make edits, comments etc.
I'll admit it ..... despite being an IT veteran of 23+ years, I've never really had to deal with integration testing until recently.
My most recent project used Pester and PowerShell to integration test the deployed system and check it was doing what it was supposed to be doing.
I learnt a lot from this exercise and wanted to share what I learnt here.
Simply put, integration testing is the act of testing a deployed version of your system to ensure it operates as it is expected to in its "integrated" state, along-side other system components.
Integration tests catch bugs that affect how code operates as part of the wider deployed system, which are not possible to catch by testing the system units alone (unit testing).
I asked Twitter to give me some tweet-sized examples of integration testing and got some great examples. Here are some of my favourites
There were also some great gifs, including this one from @Storey247.
Unit tests pass… integration tests fail pic.twitter.com/RJ0EjKMr71
— ʎǝɹoʇS ǝʌɐᗡ - ʎǝɹoʇS ǝnɹ⊥ (ノಠ益ಠ)ノ彡┻━┻ (@STOREY247) February 17, 2021
In order to perform integration tests, you'll need a thing that simulates real transactions on your system and exercises known system interfaces, then asserts that the outputs are what you expected them to be.
Throughput this article, I'll use WorldClockApi.com as a system to test; everyone can understand telling the time so it is a nice simple system to base examples on. I have nothing to do with this website. I have no idea who owns or maintains it, but it does seem to work and that is good enough for me.
According to the docs of WorldClockAPI.com, if I call this URI http://worldclockapi.com/api/json/utc/now, I should expect a json response detailing the time and some other date related information.
If I wanted to integration test this system, I would first send a request to http://worldclockapi.com/api/json/utc/now and then assert that the response was what I expected, which in this case is something like this:
{
"$id": "1",
"currentDateTime": "2021-02-17T12:57Z",
"utcOffset": "00:00:00",
"isDayLightSavingsTime": false,
"dayOfTheWeek": "Wednesday",
"timeZoneName": "UTC",
"currentFileTime": 132580402538262368,
"ordinalDate": "2021-48",
"serviceResponse": null
}
If the response is what I expected, then I can assume the system is working correctly in it's integrated state and all is well.
Fundamentally, that is all you need to know about integration testing; it is a way of testing that your system works in real life with other systems it depends on.
Pester is a PowerShell based testing framework which has a very elegant syntax for setting up tests and asserting the results. It follows an English language way of describing assertions.
Because it is based on PowerShell, you can use all of the goodness of PowerShell to call systems via either built-in cmdlets or libraries. Pester tests are written as PowerShell scripts (*.PS1) which can be easily embedded into your CI pipeline.
You can see the official overview of Pester at the Quick Start docs, but here are some of the key principles....
Individual tests (or assertions) are represented by It
blocks. In the AAA pattern, these are the assertions that we want to actually test are true or false.
Each It
is accompanied with a Should
block. Should
is a keyword that defines the assertion and has many operators such as Be
, BeGreaterThan
, Contain
and many many more
A Describe
block is a logical grouping of individual tests. In many cases, a single test file (something.tests.ps1
) may contains a single describe block.
You can use BeforeAll
to arrange/setup the test and AfterAll
to tear down afterwards. See Setup and teardown.
This is a very basic example which asserts that the variable $number
is equal to 1.
Describe "Number tests" {
BeforeAll {
$number = 1
}
It "Number is equal to 1" {
$number | Should -Be 1
}
}
Lets put Pester to use and build an integration test for WorldClockAPI.com, you can find the finished worldclockapi.test.ps1
file published on GitHub: https://github.com/martinkearn/Pester-WorldClockApi.
The first step is to install Pester, using Install-Module Pester -Force
in a PowerShell console (with administrator rights). Follow this with Import-Module Pester -PassThru
to ensure that the output is shown in the console.
Create a file called worldclockapi.test.ps1
and open it in your favourite PowerShell editor (such as Visual Studio Code).
We now need to setup the basic test structure and call the WorldClockApi. We do this in a BeforeAll
section so that we known the response should be there before any tests run. The code within the BeforeAll
is just basic PowerShell which does a HTTP request to the API to get the response (stored as $response
) and then converts that response's content to the $responseContent
object which we can use standard dot notation to drill into and inspect later.
Describe 'Test worldclockapi.com' {
BeforeAll {
$response = Invoke-WebRequest -Method 'GET' -Uri 'http://worldclockapi.com/api/json/utc/now'
$responseContent = $response.Content | ConvertFrom-Json
}
}
You can now run this in your PowerShell console using the following command
Invoke-Pester -Output Detailed .\worldclockapi.tests.ps1
There are no It
blocks yet so there are no tests to pass but providing there are no errors, you are good to continue. The response should look like this.
Now we have the basic script, we will add a range of tests using the It
and Should
keywords. Add the following code beneath the BeforeAll
closing line. The code is mostly self explanatory; in some of the tests, we have some PowerShell which gets the current date in various formats so we can make assertions against the $responseContent
object.
It "It should respond with 200" {
$response.StatusCode | Should -Be 200
}
It "It should have a null service response" {
$responseContent.serviceResponse | Should -BeNullOrEmpty
}
It "It should be the right day of the week" {
$dayOfWeek = (Get-Date).DayOfWeek
$responseContent.dayOfTheWeek | Should -Be $dayOfWeek
}
It "It should be the right year" {
$year = Get-Date -Format "yyyy"
$responseContent.currentDateTime | Should -BeLike "*$year*"
}
It "It should be the right month" {
$month = Get-Date -Format "MM"
$responseContent.currentDateTime | Should -BeLike "*$month*"
}
# These two tests assume you are running this outside daylight savings (during the winter) .. hacky but good way to showcase the syntax ;)
It "It should not be daylight savings time" {
$responseContent.isDayLightSavingsTime | Should -Not -Be $true
}
It "It should not be daylight savings time another way" {
$responseContent.isDayLightSavingsTime | Should -BeFalse
}
If you re-run the script now, you should get 7 passing tests, which should look like this in your console.
You can find the full script file on GitHub but I've included here for quick reference:
Describe "Test worldclockapi.com" {
BeforeAll {
$response = Invoke-WebRequest -Method 'GET' -Uri 'http://worldclockapi.com/api/json/utc/now'
$responseContent = $response.Content | ConvertFrom-Json
}
It "It should respond with 200" {
$response.StatusCode | Should -Be 200
}
It "It should have a null service response" {
$responseContent.serviceResponse | Should -BeNullOrEmpty
}
It "It should be the right day of the week" {
$dayOfWeek = (Get-Date).DayOfWeek
$responseContent.dayOfTheWeek | Should -Be $dayOfWeek
}
It "It should be the right year" {
$year = Get-Date -Format "yyyy"
$responseContent.currentDateTime | Should -BeLike "*$year*"
}
It "It should be the right month" {
$month = Get-Date -Format "MM"
$responseContent.currentDateTime | Should -BeLike "*$month*"
}
# These two tests assume you are running this outside daylight savings (during the winter) .. hacky but good way to showcase the syntax ;)
It "It should not be daylight savings time" {
$responseContent.isDayLightSavingsTime | Should -Not -Be $true
}
It "It should not be daylight savings time another way" {
$responseContent.isDayLightSavingsTime | Should -BeFalse
}
}
Integration testing is an important process for ensuring that your various system component work well together in their deployed state. It is usefull at the end of the project but also during development as you are building our components.
Pester and PowerShell ae a very flexible way to integration test using simple, well established PowerShell syntax, cmdlets and the easy to follow syntax of Pester.
For more resources:
Got a comment?
All my articles are written and managed as Markdown files on GitHub.
Please add an issue or submit a pull request if something is not right on this article or you have a comment.
If you'd like to simply say "thanks", then please send me a .