Powershellを久しぶりに使う機会があり、テストしながらスクリプト書きたいな~と調べてたら、Pesterというのがお手軽でわかりやすかったので使ってみることにしました。
昔、psexpectを少し使ってみましたが、Pesterの方が個人的にはわかりやすくて好きだなぁ。 PSExpectでTDD(FizzBuzzでいこう) - なか日記
準備
使うにあたって、簡単な準備が必要です。
ダウンロード
GitHubのページGitHub - pester/Pester: Pester is the ubiquitous test and mock framework for PowerShell.から一式をcloneもしくはダウンロードします。
適当な場所へ配置
zip形式でダウンロードした場合には適当な場所に展開しておきます。
モジュールのインポート
Powershellのコンソールを起動して、Pesterのモジュールをロードしておきます。
> Import-Module Pester\Pester.psm1
使ってみる
それではさっそく使ってみましょう。
ソースの生成
Pesterには製品コードとテストコードの雛形を自動生成してくれる機能があります。コンソールで以下のコマンドレットを実行します。
> New-Fixture .\scripts Sample
Creating => scripts\Sample.ps1
Creating => scripts\Sample.Tests.ps1
すると、scriptsディレクトリ配下に製品コード(Sample.ps1)とテストコード(Sample.Tests.ps1)が生成されます。
それぞれの中身は以下の様になっています。
scripts\Sample.ps1
function Sample { }
scripts\Sample.Test.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".") . "$here\$sut" Describe "Sample" { It "does something useful" { $true | Should Be $false } }
実行結果をパイプラインで繋いで、期待値と比較させています。
テストの実行
とりあえず、テストを実行してみましょう。テストを実行するには Invoke-Pester コマンドレットを使用します。
> Invoke-Pester Executing all tests in D:\data\Poweshell\PesterSample Describing Sample [-] does something useful 3ms Expected: {False}, But was {True} at line: 8 in D:\data\Poweshell\PesterSample\scripts\Sample.Tests.ps1 Tests completed in 3ms Passed: 0 Failed: 1
アサーションが $true | Should Be $false
となっているのでテストは失敗します。
ちなみに、テストの実行は以下の様にテストファイルを指定したり、テストファイル内のテストを指定して実行したりもできます。
> Invoke-Pester .\scripts\Sample.Tests.ps1 > Invoke-Pester .\scripts\Sample.Tests.ps1 Sample
テストの書き方
詳しくは「Home · pester/Pester Wiki · GitHub」に載っていますが、簡単に紹介しておきます。
サンプルその1
Describe "Sample" {
Context "○○の場合" {
It "テストケース1" {
$true | Should Be $true
}
It "テストケース2" {
$true | Should Be $true
}
Context "○○の場合" {
It "テストケース3" {
$true | Should Be $true
}
}
}
Context "××の場合" {
It "テストケース4" {
$true | Should Be $true
}
}
}
Describe | テストの宣言。MSTestでいうと、TestClassというところかな。この単位で$TestDriveのディレクトリが初期化されます |
Context | テストケースをグルーピングするのに使用します。入れ子にもできるみたい。 |
It | テストケース。MSTestでいうと、TestMethodかな。 |
アサーション
よく使いそうな物をピックアップします*1。コードは全てグリーンになるパターンで書いてます。
Be
オブジェクトが等しいかどうかを評価します。
It "Be" {
"hoge" | Should Be "hoge"
}
Exist
ファイル(オブジェクトでも文字列でも)が存在するかどうかを評価します。
It "Exist" {
"C:\Windows" | Should Exist
Get-Item "C:\Windows" | Should Exist
}
Contain
指定されたファイルの中に特定の文字列を含んでいるかどうかを評価します。
It "Contain" {
"hoge.txt" | Should Contain "hoge contents"
}
BeNullOrEmpty
オブジェクトがnullまたは空文字列かどうかを評価します。
It "BeNullOrEmpty" {
$null | Should BeNullOrEmpty
"" | Should BeNullOrEmpty
}
Match
文字列が正規表現にマッチするかどうかを評価します。
It "Match" {
"hoge" | Should Match "[Hh]oge"
}
Throw
スクリプトブロックが例外を出力するかどうかを評価します。評価するのは例外のオブジェクトではなく、メッセージ(文字列)になります。
It "Throw" {
{throw "error message"} | Should Throw "error message"
}
その他
Setup
MSTestでいうTestInitializeとは全然違うので注意が必要です。 $TestDrive(%Temp%\pester) のフォルダにファイルやフォルダを作成するコマンドになります。 $TestDrive は Describe の単位で初期化されますので、テストケースで行った操作が他のテストケースに影響する場合があります。
Describe "Setup" {
Setup -File "hoge.txt" "content"
Setup -Dir "fuga"
It "Contain" {
"$TestDrive\hoge.txt" | Should Contain "content"
"$TestDrive\fuga" | Should Exist
}
It "Delete" {
Remove-Item "$TestDrive\hoge.txt"
"$TestDrive\hoge.txt" | Should Not Exist
}
It "Exist" {
"$TestDrive\hoge.txt" | Should Exist #テストに失敗します
}
}
最後に
その他にもMockが使えたり、機能は多そうですが今のところ上記機能で十分なので今回はこれで終わります。もっと知りたい人はソースを見るとか、bingってみるとか、今年のPowerShell Advent Calendar 2013にエントリPesterのMock機能をもう少し詳しくを上げられた[twitter:@oota_ken]さんに聞くとか*2して頂ければと思います。