Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
549 views
in Technique[技术] by (71.8m points)

powershell - Show content of hashtable when Pester test case fails

Problem

When a Hashtable is used as input for Should, Pester outputs only the typename instead of the content:

Describe 'test' {
    It 'test case' {
        $ht = @{ foo = 21; bar = 42 }
        $ht | Should -BeNullOrEmpty
    }
}

Output:

Expected $null or empty, but got @(System.Collections.Hashtable).

Expected output like:

Expected $null or empty, but got @{ foo = 21; bar = 42 }.

Cause

Looking at Pester source, the test input is formatted by private function Format-Nicely, which just casts to String if the value type is Hashtable. This boils down to calling Hashtable::ToString(), which just outputs the typename.

Workaround

As a workaround I'm currently deriving a class from Hashtable that overrides the ToString method. Before passing the input to Should, I cast it to this custom class. This makes Pester call my overridden ToString method when formatting the test result.

BeforeAll {
    class MyHashTable : Hashtable {
        MyHashTable( $obj ) : base( $obj ) {}
        [string] ToString() { return $this | ConvertTo-Json }
    }
}

Describe 'test' {
    It 'test case' {
        $ht = @{ foo = 21; bar = 42 }
        [MyHashTable] $ht | Should -BeNullOrEmpty
    }
}

Now Pester outputs the Hashtable content in JSON format, which is good enough for me.

Question

Is there a more elegant way to customize Pester output of Hashtable, which doesn't require me to change the code of each test case?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Somewhat of a hack, override Pester's private Format-Nicely cmdlet by defining a global alias of the same name.

BeforeAll {
    InModuleScope Pester {
        # HACK: make private Pester cmdlet available for our custom override
        Export-ModuleMember Format-Nicely
    }

    function global:Format-NicelyCustom( $Value, [switch]$Pretty ) {
        if( $Value -is [Hashtable] ) {
            return $Value | ConvertTo-Json
        }
        # Call original cmdlet of Pester
        PesterFormat-Nicely $Value -Pretty:$Pretty
    }

    # Overrides Pesters Format-Nicely as global aliases have precedence over functions
    New-Alias -Name 'Format-Nicely' -Value 'Format-NicelyCustom' -Scope Global
}

This enables us to write test cases as usual:

Describe 'test' {
    It 'logs hashtable content' {
        $ht = @{ foo = 21; bar = 42 }
        $ht | Should -BeNullOrEmpty
    }   

    It 'logs other types regularly' {
        $true | Should -Be $false 
    }
}

Log of 1st test case:

Expected $null or empty, but got @({
 "foo": 21,
 "bar": 42
}).

Log of 2nd test case:

Expected $false, but got $true.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...