Search code examples
powershellunit-testingtestingpester

Pester, Powershell How to go about and implement both tests with external data and non-external data?


See also: https://github.com/pester/Pester/discussions/2404#discussioncomment-7597861
I'm trying to set up tests using Pester with both external and non-external data. I've created separate test files for these scenarios and used Invoke-Pester with containers, but I'm facing a couple of issues:

Split Summaries: When I run the tests with external data, the summaries are split, and it doesn't provide a clear overall picture of test results.

Tests Passed: 1, Failed: 1, Skipped: 0 NotRun: 0
...
Tests Passed: 1, Failed: 0, Skipped: 0 NotRun: 0

rather than

Tests Passed: 2, Failed: 1, Skipped: 0 NotRun: 0

Passing Configuration: I'm unsure how to pass a configuration (-Configuration) into the inner Invoke-Pester call (Invoke-ExternalData.Tests.ps1)

Here's the structure I'm using:

NonDataExternal.Tests.ps1:

Describe "behaviour" {
    It "should be able to access the parameter" {
        "value" | Should -Be "value"
    }
}

ExternalData.ps1:

param(
    [Parameter(Mandatory)]
    $Param
)

Describe "behaviour" {
    It "should be able to access the parameter" {
        $Param | Should -Be "value"
    }
}

Invoke-ExternalData.Tests.ps1:

$values = 'value', 'not value'
$containers = $values | ForEach-Object {
    New-PesterContainer -Path "$PSScriptRoot/ExternalData.ps1" -Data @{ Param = $_ }
}
Invoke-Pester -Container $containers

I would appreciate guidance on how to structure these tests to achieve a unified summary and how to pass a configuration into the inner Invoke-Pester call. Is there a way to "hand-off" the PesterContainer objects without invoking Pester again?


Solution

  • My solution is to change ExternalData.ps1 and Invoke-ExternalData.Tests.ps1
    -ForEach essentially injects the variables that are available in discovery to the Run phase ExternalData.ps1

    param(
        [Parameter(Mandatory)]
        $Param
    )
    BeforeDiscovery {
        # Gather initial values for generating tests
        $ExtraParam = 'value'
    }
    Describe 'Test Container' -ForEach @(@{Param = $Param; ExtraParam = $ExtraParam }) {
        BeforeAll {
    
        }
        BeforeEach {
    
        }
        AfterEach {
    
        }
        AfterAll {
    
        }
        It 'Test with value <Param>' {
            $Param | Should -Not -Be $null
            $ExtraParam | Should -Not -Be $null
        }
    }
    

    Invoke-ExternalData.Tests.ps1

    BeforeDiscovery {
        $values = ,'value', 'not value'
    }
    Describe 'Test with value <value>' -ForEach $values {
        & "$PSScriptRoot/ExternalData.ps1" $_
    }