We're at maybe 50% of the way to minimum viable product..? Don't expect this to be useful right now.
A module for generating unit tests for Powershell modules.
Let's say you have a module that acts as an API client, and it currently functions as intended, but it has no unit tests. To retrospectively write unit tests by hand can be time-consuming; that's where Gigo steps in.
Gigo treats functions under test as black boxes. It captures:
- The invocation of a function (the function name and the bound parameters)
- The errors and exceptions generated by the function
- The output of the function
- Additionally:
- Any invocations of Invoke-RestMethod
- Any errors and exceptions generated by Invoke-RestMethod
- The output of Invoke-RestMethod
It does not capture:
- Session state (global variables)
- Internal behaviour
Gigo does not test your code deeply, but it does ensure that, for any given input, the behaviour of the system under test doesn't change.
Gigo usage consists of these steps:
- Add Gigo to your project (it does not need to be distributed with your packaged module)
- Generate a test suite of Pester tests
- Customise the test suite by tailoring the function invocations
- Run the test suite in capture mode
- Save the captured data and commit to source control
- To run your unit tests, invoke pester as normal with Gigo in "run" mode (the default)
Pick the commands that you wish to test.
Run:
New-GigoPesterSuite -Commands <names of commands to test> -OutFile <path to place tests>
This will generate valid Pester test scripts in the sepcified path.
In your preferred script editor, edit the generated test scripts from the previous stage.
Generated tests look like this:
Describe 'Command: Get-ApiStuff' {
Context 'ParameterSet: ByCategory' {
# Get-ApiStuff -Category {CategoryA | CategoryB | CategoryC} [<CommonParameters>]
$InvocationsToTest = @(
{Get-ApiStuff -Category 'CategoryA'},
{Get-ApiStuff -Category 'CategoryB'},
{Get-ApiStuff -Category 'CategoryC'}
)
foreach ($Invocation in $InvocationsToTest)
{
It "$GigoModeString`: $Invocation" {
$Invocation | Invoke-Gigo | Should -BeNullOrEmpty
}
}
}
}
You must edit the scriptblocks in $InvocationsToTest
to reflect the code paths that need to be tested. You can add as many as you want but, of course, the tests will take longer to run.
If you run the test suite now, you will get a lot of this error text:
ERROR: Gigo was asked to compare invocation {Get-ApiStuff -Category 'CategoryA'} to previous trace, but no trace has been captured for that invocation.
You need to capture the trace first. Set Gigo into Capture mode:
Set-Gigo -Mode Capture
Then run Pester:
Invoke-Pester <path to generated tests>
If you have $VerbosePreference
set to Continue
, you will see a lot of this:
VERBOSE: Gigo is capturing trace for invocation {Get-ApiStuff -Category 'CategoryA'}
Once this has completed, commit the test scripts and the captured trace to your source control repository (e.g. git). Your test suite consists of the tests scripts and the capture. (Gigo needs to be present at test time to marry the two together into runnable tests.)
If Gigo is still Capture mode, set it back to Run mode:
Set-Gigo -Mode Run
(Run mode is the default, so you won't need to do this every time.)
Run your test suite as normal:
Invoke-Pester <path to generated tests>
The first time you run this, all your tests should pass! But, should someone introduce a breaking change to the code, the changed behaviour will appear as follows:
Context ParameterSet: ByCategory
[-] Error occurred in It block 362ms
Expected null, but got @{ApiException = '404: not found'}.
74: $Invocation | Invoke-Gigo | Should -Be Null
at <ScriptBlock>, C:\dev\MyProject\Test\Gigo.BlackBox.Test.ps1: line 74
at DescribeImpl, C:\Users\username\Documents\WindowsPowerShell\Modules\Pester\Functions\Describe.ps1: line 161