PesterでPowerShellの単体テスト自動化

PowerShellを(ちょっとだけ)使ったシステムを作っていて、単体試験フレームワークが必要になり調査したので覚書を残します。本腰入れて調査したわけではないのですが、Pesterがデファクトスタンダードっぽい雰囲気です。(Windows10やWindows Server 2016にはデフォルトで入っています)
なのでPesterの使い方を簡単に記載します。レポート作成は準備も多いので別記事で紹介します。



インストール(or アップデート)

Windows10では V3系がデフォルトで入っていますが、現在の最新(4系)と一部互換性がないので更新しておくのが良いと思います。Jacoco形式でカバレッジ出せるようになるのも4系からです。インストールは下記で可能です。
Install-Module -Name Pester -Force
既にインストールされている場合は警告が出るかもしれません。無視するなら下記。
Install-Module -Name Pester -Force -SkipPublisherCheck
※デフォルトではPSSecurityExceptionが発生してPowerShellスクリプトを実行できない場合があります。その場合はこちら等を参考に実行許可してください。

モデルケース

実用的な例ではない気がしますが、PowerShellからPythonスクリプトを起動して処理を行うシステムを想定します。ディレクトリ構成は下記です。

├─PS
│  ├─script0
│  │      script0.ps1
│  ├─script1
│  │      script1.ps1
│  └─test
│      ├─script0
│      │      script0.Tests.ps1
│      └─script1
│             script1.Tests.ps1
└─pythonScripts
        script0.py
        script1.py

PesterのExampleはスクリプトとテストコードは同じディレクトリに入れているようですが、あまりそうしたくない事情ってありますよね。通常のディレクトリ構成だとNew-Fixtureコマンドでテストのひな形が簡単に作れるのですが、自分で決めたディレクトリ構成だとテスト対象ファイルの指定をちょっといじる必要があります。(後述)

テストの記述

テスト対象スクリプトの指定

テスト対象ファイルは下記のようにパスを取得して指定します。

# カレントの取得
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
# test\を除けばテスト対象ディレクトリになる
$script_dir = $here -replace "test\\", ""
# .Testsを除けばテスト対象ファイルになる
$test_file = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
$test_target = Join-Path $script_dir $test_file

$python_dir = Join-Path (Split-Path -Parent $script_dir) pythonScripts
# テストファイルを読み込む
. $test_target

テストコードと説明の記述

Describe:テストの説明、Context:テストのグループ名、It:テストケースと記載していきます。Contextは省略可能です。
Mock化したい場合は Mock 関数名 {期待動作} で実現可能です。ちなみに詳しくは不明ですが、Mock化した関数を使用してスクリプトのテストをする場合は
powershell スクリプトパス ではなく、& スクリプトパス で実行します。

Describe "CallPythonの動作確認" {
    Context "正常系" {
        It "script0.pyを起動する場合" {
            CallPython "script0.py" | Should Be 0
        }
        It "script1.pyを起動する場合" {
            CallPython "script1.py" | Should Be 1
        }
    }
    Context "異常系" {
        It "ファイルがない場合" {
            CallPython "notFound.c" | Should Be 2
        }
    }
}

Describe "スクリプト全体の動作確認" {
    Context "正常系" {
        It "script0.pyを起動する場合" {
            & $test_target | Should Be 0
        }
    }
    Context "異常系" {
        It "CallPythonが1を返すようMock化" {
            Mock CallPython { return 1 }
            & $test_target | Should Be 1
        }
        It "CallPythonが2を返すようMock化" {
            Mock CallPython { return 2 }
            & $test_target | Should Be 1
        }
    }
}

テストの実行

testディレクトリ(テストスクリプトのルート)で下記コマンドを実行すると配下のすべてのテストスクリプト(*.Tests.ps1)を実行してくれます。
Invoke-Pester

実際はカバレッジレポートを出したり成功失敗のレポートを出したりすると思うので色々オプションを指定します。レポート作成は色々準備も必要なので別記事へ。


カテゴリー:PowerShell,Windows,自動化

Output不足なエンジニア

統計が好きになれず、機械学習やったら必然的に統計が必要になるだろうと思ったら想像以上に機械学習にハマる。数学は芸術なので商売にするつもりはないけど、DeepLearningは数学じゃないし商売にしたいと思っているところ。画像処理がメイン。