しばたテックブログ

気分で書いている技術ブログです。

Pesterでカスタムアサーションを行う

【2017/11/01追記】

Pester 4.0.5から正式にカスタムアサーションを行うことができる様になりました。
詳細はこちらのエントリをご覧ください。

blog.shibata.tech

【追記ここまで】


前回の続きというわけではないのですが...
元ネタはこちら。

kamranicus.com

はじめに

大前提としてPester標準の機能としてカスタムアサーションを行うことはできません。

本エントリでは、元ネタにある通りPesterの内部動作をハックすることでカスタムアサーションを実現しています。
本エントリの内容はPester 3.4.0で動作確認していますが、将来Pesterの内部動作が変わった場合は実現できなくなる可能性があります。

このため現実的にはあまり使えない方法かもしれません。
こういった方法もあるよということで参考にしていただければと思います。

PesterのShouldコマンド

Shouldの基本動作

Pesterでのテストは以下の簡単な例の様に[テスト内容] | Should [動詞] [期待される値]の形で行うのが基本です。

Describe "テスト" {
    It "足し算のテスト" {
        1 + 1 | Should Be 2
    }
}

Shouldで利用可能な動詞は現在のところ以下となります。

動詞 内容
Be 等価比較(-eq)
BeExactly 等価比較(-ceq)
BeGreaterThan 大小比較(-gt)
BeLessThan 大小比較(-lt)
BeLike 文字列比較(-like)
BeLikeExactly 文字列比較(-clike)
BeOfType 型の比較(-is)
Exist ファイルなどの存在チェック(Test-Path)
Contain ファイル中の文字列チェック(Get-Content + -match)
ContainExactly ファイル中の文字列チェック(Get-Content + -cmatch)
Match 文字列中のパターンチェック(-match)
MatchExactly 文字列中のパターンチェック(-cmatch)
Throw 例外となるかチェック
BeNullOrEmpty NULLチェック

Shouldの内部動作

1. Pester[動詞]

これらの動詞はPester内部ではPester[動詞]という名前の関数で定義されており、ソースコード上は/Functions/Assertionsディレクトリに存在しています。

Beの場合であれば以下の様になっています。

# Pester/Functions/Assertions/Be.ps1 より
function PesterBe($value, $expected) {
    return ($expected -eq $value)
}
2. Pester[動詞]FailureMessage

また、テストに失敗したときのエラーメッセージ出力用にPester[動詞]FailureMessageという関数が使われています。
こちらもBeの場合は以下の様になっています。

# Pester/Functions/Assertions/Be.ps1 より一部抜粋
function PesterBeFailureMessage($value, $expected) {
    if (-not (($expected -is [string]) -and ($value -is [string])))
    {
        return "Expected: {$expected}`nBut was:  {$value}"
    }

    # ・・・後略・・・
}
3. NotPester[動詞]FailureMessage

最後にNotPester[動詞]FailureMessageという関数が使われています。
こちらはShould Not Beの様にNotと併せて使われた際のエラーメッセージ出力用の関数となります。

Beの場合の定義は以下。

# Pester/Functions/Assertions/Be.ps1 より
function NotPesterBeFailureMessage($value, $expected) {
    return "Expected: value was {$value}, but should not have been the same"
}
注意事項

Should内部では与えられた引数の順番で"テスト内容"($Value)か"期待される値"($Expected)かの判定を行っているため、上記3関数の引数の順序を変えてはいけません。

Pesterでカスタムアサーションを行う

ここまでの内容を踏まえて、Pesterでカスタムアサーションを行うには以下の3関数を定義してやれば良いことがわかります。

  1. Pester[動詞]
  2. Pester[動詞]FailureMessage
  3. NotPester[動詞]FailureMessage

元ネタではこれらの関数をモジュールに組み込むところまで行っていますが、最低限テスト中で必要な関数が定義されていればカスタムアサーションは可能ですので本エントリではそこまではしません。

カスタムアサーション例

Gistに簡単な例を上げました。
こちらの例ではHashtableを比較するためのBeHashという動詞を新たに定義しています。

gist.github.com

Pesterでカスタムアサーションを行うサンプル

実行結果

通常Be(-eq)ではHashtableの比較はできないため以下の様にエラーとなります。

f:id:stknohg:20161130032051p:plain

これが新たに定義したBeHashを使えばきちんと比較することができます。

f:id:stknohg:20161130032250p:plain

キーの値が異なる場合はちゃんとエラーとなります。

f:id:stknohg:20161130032524p:plain