PowerShellでユニットテスト(Pester)

# <i class="fa fa-cubes" style="font-size:1em;"></i> 概要

Pesterを使ったPowerShellスクリプトのユニットテスト方法。

# <i class="fa fa-cubes" style="font-size:1em;"></i> 環境
* Windows 10
* PowerShell V5
* Pester 3.4.4

# <i class="fa fa-cubes" style="font-size:1em;"></i> ダウンロード、展開
Pesterをダウンロード。

**※PowerShell V5には最初から入っているかも。**

[GitHub - pester/Pester: PowerShell BDD style testing framework](https://github.com/pester/Pester)

![pes01.png](https://qiita-image-store.s3.amazonaws.com/0/142879/1b636b2c-3584-9ac7-e5eb-4b6d6ee89724.png)

ダウンロードしたzipファイルを右クリック、プロパティでブロックの解除してから適当な場所に展開。
![pes02.png](https://qiita-image-store.s3.amazonaws.com/0/142879/9bf2379e-9ea7-6e99-aa9a-7bb0df6647af.png)

# <i class="fa fa-cubes" style="font-size:1em;"></i> ひな形の生成

## <i class="fa fa-cube" style="font-size:1em;"></i> モジュール読み込み

Pesterモジュールを読み込む。

```PowerShell
Import-Module .\Pester.psm1
```

## <i class="fa fa-cube" style="font-size:1em;"></i> ひな形生成

スクリプト格納用のディレクトリ作成。

```PowerShell
md Test
```

作成したディレクトリの中にひな形出力。

```PowerShell
New-Fixture .\Test Test1
```

```PowerShell:実行結果
    ディレクトリ: C:\Work\Pester\Test


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2016/12/11     20:19             26 Test1.ps1
-a----       2016/12/11     20:19            250 Test1.Tests.ps1
```

生成されたファイル。

```PowerShell:Test1.ps1
function Test1 {

}
```

```PowerShell:Test1.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

Describe "Test1" {
    It "does something useful" {
        $true | Should Be $false
    }
}
```
# <i class="fa fa-cubes" style="font-size:1em;"></i> 実行

## <i class="fa fa-cube" style="font-size:1em;"></i> ひな形のテストコード実行

とりあえず実行してみる。
`Pester.psm1`の読み込みは先ほどやったので省略。
`Invoke-Pester`でテストファイルを読み込ませる。
`[+]`緑なら期待通りの結果、`[-]`赤なら期待とは違うという意味。
赤いのでテスト失敗。
![pes03.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6db3cad8-a117-91e5-2773-f83631559d02.png)


`Test1.Test.ps1`を修正する。
`Should Be $false`は、結果が`$false`であることを期待するので、パイプラインの左側を`$true`から`$false`に修正して保存する。

```PowerShell:Test1.Tests.ps1（抜粋）
        $false | Should Be $false
```

もう一度実行。
今度は成功。
![pes04.png](https://qiita-image-store.s3.amazonaws.com/0/142879/419c124b-df10-a586-6179-51cce72bebee.png)

## <i class="fa fa-cube" style="font-size:1em;"></i> 色々試す

色々追加してみる。

```PowerShell:Test1.ps1
function Test1([int]$i) {
    1000 / $i
}

function StrTest1([string]$msg) {
    $msg + $msg
}
```

`Describe`にそのテストの説明を書く。
`Context`でテストをグルーピングすることができる。 
`It`が具体的なテストケース。

```PowerShell:Test1.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

Describe "Test1の動作確認" {
    Context "正常系の確認" {
        It "1000を与えたら1が返るはず" {
            Test1 1000 | Should Be 1
        }
        It "200を与えたら5が返るはず" {
            Test1 200 | Should Be 5
        }
    }
    Context "異常系の確認" {
        It "0を渡したら例外が発生するはず" {
            {Test1 0} | Should Throw
        }
        It "数値以外を渡したら例外が発生するはず" {
            {Test1 "aaa"} | Should Throw
        }
    }
}
Describe "StrTest1の動作確認" {
    It "aaaを渡したらaaaaaaが返るはず" {
        StrTest1 "aaa" | Should Be "aaaaaa"
    }
    It "aaaを渡したらbbbは返らないはず" {
        StrTest1 "aaa" | Should Not Be "bbb"
    }
    It "nullを渡したらnullが返るはず" {
        StrTest1 $null | Should BeNullOrEmpty
    }
}
Describe "その他" {
    It "0より大きいはず" {
        5 | Should BeGreaterThan 0
    }
    It "100より小さいはず" {
        99 | Should BeLessThan 100
    }
    It "Test1.ps1はカレントディレクトリに存在するはず" {
        ".\Test1.ps1" | Should Exist
    }
    It "文字列型のはず" {
        "あああ" | Should BeOfType System.String
    }
    It "abで始まるはず(大文字・小文字区別なし)" {
        "ABCDefg" | Should BeLike "ab*"
    }
}
```

実行してみる。`Invoke-Pester`に引数を指定しない場合はカレント配下にあるテストファイルを全部実行。
![pes05.png](https://qiita-image-store.s3.amazonaws.com/0/142879/dd031ae2-fd3d-3c80-d2d0-96d05ea15fe0.png)

`Test1.Test.ps1`の`Describe "その他"`の中に失敗ケースを入れてみる。

```PowerShell:Test1.Tests.ps1（抜粋）
    It "abで始まるはず(大文字・小文字区別あり)" {
        "ABCDefg" | Should BeLikeExactly "ab*"
    }
```

`Invoke-Pester`で実行。
予想結果が「小文字のabで始まる」に対し、入力が`ABCDefg`なのでテスト失敗。
![pes06.png](https://qiita-image-store.s3.amazonaws.com/0/142879/30be4381-fcc7-260c-d2db-756f6fe36cb1.png)

# <i class="fa fa-cubes" style="font-size:1em;"></i> テスト結果のファイル出力

```PowerShell
Invoke-Pester -OutputFormat NUnitXml -OutputFile テスト結果.xml
```

# <i class="fa fa-book" style="font-size:1em;"></i> 参考サイト

* [Home · pester/Pester Wiki · GitHub](https://github.com/pester/Pester/wiki)