fsackur / _Gigo

Auto-generate black-box unit tests for Powershell API modules

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WORK IN PROGRESS

We're at maybe 50% of the way to minimum viable product..? Don't expect this to be useful right now.

Gigo

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.

Black box testing

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.

Usage

Overview

Gigo usage consists of these steps:

  1. Add Gigo to your project (it does not need to be distributed with your packaged module)
  2. Generate a test suite of Pester tests
  3. Customise the test suite by tailoring the function invocations
  4. Run the test suite in capture mode
  5. Save the captured data and commit to source control
  6. To run your unit tests, invoke pester as normal with Gigo in "run" mode (the default)

Generate a test suite

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.

Customise the test suite

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.

Run the test suite in capture mode

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.)

Run the tests to test your code

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

About

Auto-generate black-box unit tests for Powershell API modules

License:MIT License


Languages

Language:PowerShell 100.0%