Pester icon indicating copy to clipboard operation
Pester copied to clipboard

Possibility to run a code block when a test fails, or assert a failed count

Open johlju opened this issue 4 years ago • 1 comments
trafficstars

Summary of the feature request

As a user I'd like to be able to output a big chunk of text (like a log) when a test does not pass. This would be very useful in situations where there a several of thousands of tests to be able to add more information around the actual test. Today it is only possible to evaluate failed test at the end of a run. Outputting these chunks of text (like a log) at the end of the run will loose the context of why it was outputted.

How should it work?

This can be either a scriptblock that runs, or a that Pester sets and PesterFailedTest variable per It-block that can be evaluated in the AfterAll or AfterEach. I would prefer to have a failed count that could even have meta data around the test that failed. There might be a need for a cmdlet Write-PesterMessage so that the output is formatted correctly in Pesters output stream.

Assuming the code that handles this must run after an It-block has run since the the logs that should be outputted might not exist until after something have been executed inside an It-block.

Option 1 - Using scriptblock

It could be a parameter RunScriptBlockOnFail that takes a scriptblock. The parameter can be added on Should, but it can also be added to the It, Context, and or Describe.

Describe 'Something' {
    BeforeAll {
        $onFailScriptBlock = {
            $content = Get-Content -Path './location/summary.txt'

            Write-PesterMessage -Message $content
        }
    }

    Context 'When executing something' {
        It 'Should have this result' -RunScriptBlockOnFail $onFailScriptBlock {
            $false | Should -BeTrue
        }
    }
}

Option 2 - Using a Pester PesterFailedTest variable

Option 2a

It could be a PesterFailedTest variable that holds metadata around the failed tests and are Context aware.

Describe 'Something' {
    AfterAll {
        # Unique variable 'PesterFailedTest' that Pester owns.
        if ($PesterFailedTest.All.Count)
        {
            $content = Get-Content -Path './location/summary.txt'

            Write-PesterMessage -Message $content
        }
    }

    Context 'When executing something' {
        AfterEach {
            # Unique variable 'PesterFailedTest' that Pester owns.
            if ($PesterFailedTest.CurrentContextAndChildContexts.Count)
            {
                $content = Get-Content -Path './location/summary.txt'

                Write-PesterMessage -Message $content
            }
        }

        It 'Should have this result' {
            $false | Should -BeTrue
        }
    }
}

Option 2b

It can also be made simpler by just count all failed test regardless in what context it failed in and have a Reset-PesterFailedTestCount (we can name it better) to reset the count if the user so desires.

Describe 'Something' {
    Context 'When executing something' {
        BeforeEach {
            Reset-PesterFailedTestCount
        }

        AfterEach {
            # Unique variable 'PesterFailedTest' that Pester owns.
            if ($PesterFailedTest.Count)
            {
                $content = Get-Content -Path './location/summary.txt'

                Write-PesterMessage -Message $content
            }
        }

        It 'Should have this result' -ForEach @($true, $false) {
            $_ | Should -BeTrue
        }
    }
}

johlju avatar Jan 05 '21 12:01 johlju

Related to #318. That should probably enable some view to indicate if a test in the currentblock failed. No ETA atm.

fflaten avatar Jul 17 '22 08:07 fflaten