本記事は PowerShell Advent Calendar 2019 の 8 日目の記事です。
はじめに
PowerShell のテストといえばWindows標準搭載のPesterが有名ですが、これまであまり使う機会がありませんでした。今回インフラバッチ用のツールをテストするために使う機会があったので、考えたことなどを残しておこうと思います。
Pester とは
BDDスタイルの開発手法を支援するテストランナーです。
pester/Pester: Pester is the ubiquitous test and mock framework for PowerShell.
BDDスタイルというのはテスト駆動開発(TDD)から派生した開発手法で、実装とテストのフェーズを分けるのではなく、テストと実装を並行して進めていく開発手法です。BDDは、TDDよりもプログラムの振る舞いを重視する点が異なるようですが、あまり区別せずTDD/BDDのように併記されることも多いようです。詳細は Wikipedia の[ビヘイビア駆動開発] (https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%98%E3%82%A4%E3%83%93%E3%82%A2%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA) を参照してください1。
テストランナーというのはその名の通り、テストを実行するためのツールです。後述しますが、PowerShellで書いたテストプログラムをフォルダに置いておくと、Pesterを実行したタイミングでテストプログラムが実行されれます。テストケースを手作業で一つずつ消化する場合に比べて省力化が期待できます。
Pester は Windows 10(PowerShell v5) に標準で搭載されており、あと1ヶ月でWindows7がサポート切れを迎えることを考えると、今後は普遍的に利用できるツールだと考えて良いのかもしれません。
Pester の使い方について簡単に
Pesterを使うには、「テストされるプログラム」と「テストするプログラム」をそれぞれ作成し、PowerShell のコンソールで Invoke-Pester
を実行します。このとき「テストするプログラム」は、「テストされるプログラム」と同じ名前で拡張子を .Tests.ps1
にしておきます。すると、pester はそれらの関係を認識してテストを実行してくれます。
テストの結果は、ちょうど tree コマンドの出力のように階層構造になってテスト項目が PowerShell コンソールに出力されます。テスト項目は視覚的にOK/NGが分かるように色分けされるので、自動でテストが流れるからといってNGを見落とすことはありません。
使い方と結果の見方についての具体的な例は、別の記事が参考になるのでそちらを参照してください。
PowerShellでユニットテスト(Pester) - Qiita
Pester を使うことになった背景について
Windowsサーバのサポート切れに伴うリニューアルプロジェクトで、VBSで実装されていたバッチ処理ツールを、PowerShellに移植する仕事をしました。そのツールはある程度汎用的に作られていたため、単純なインフラバッチに比べて多くの条件分岐があり、小規模なアプリのようになっていました2。
移植するにあたって、PMから条件分岐レベルでちゃんとテストするように指示がありましたが、従来のようにテストケースを手作業で消化する手法では、期限までに納得を得られる結果を出すことが難しそうに思いました。
Pester を使うことにした理由
「ちゃんとテストした」ことを示すために目をつけていた Pester の機能は、CodeCoverrage オプションです。これは、テストの網羅率を出力するオプションで、行単位で実行(テスト)されたかどうかをチェックできます。実行されたかどうかだけの機械的な出力であるため、入念なコードレビューなど無くても「ちゃんとテストした」ことを納得させることができると考えました。
CodeCoverrage については、Pester の wiki に具体例があります。
Code Coverage · pester/Pester Wiki
Pester をインフラバッチ開発のテストに使ってみた結果
まず、CodeCoverrage
については、PMから大きな追求もなく納得させることができ、期待通りの効果が得られました。その他に、Pester の良かったところについて、以下に述べます。
これは Pester というか BDD という手法の良いところなのですが、実装とテストを並行して進めることができるため、問題に早期に気づくことができました。これによってバグを探して数時間。。。のようなことがありませんでした。これまで通りのスケジュール感で実装していると、テストする予定だった期間が余るという貴重な体験をしました。また、用意したテストプログラムは何度でも機械的に実行できるため、人為的なテスト不備やリグレッションテストの手間が無くなった点も良かったと思います。尚、リリース後の機能的なバグは今の所見つかっていません。
次に、辛かったところについて。
良いところの裏返しでもあるのですが、テストプログラムを書くのが面倒でした。テストの書き方は単純ではあったものの、書き慣れていない内は開発ペースが遅れているように感じられて焦ります。また、インフラバッチの特徴として外部リソース(サービスやファイル)を操作する処理が多いため、擬似的に外部リソースを再現する機能である Mock
や TestDrive
を多用することになるのですが、さすがに疑似的に再現した環境ではテストに不備が見つかり、従来の手作業によるテストが必要でした。
おわりに
インフラバッチ開発のテストに Pester を使ってみて、正直なところアプリ的過ぎて使う場面は限られるだろうなぁという気持ちが強いです。上述の通り、メモリ上でゴニョゴニョすることが多いアプリ開発とは違って、インフラバッチは外部リソースへのアプローチが多いため、疑似環境を多用せざるをえずテストの精度が落ちてしまう点が気になりました。一方で、テストの属人性を排除できたり、リグレッションテストの手間が無くなったりする快適さは確かに有り、今後活用できる方向が見つかれば良いなぁと思います。
早速ですが活用できそうな方向が見つかったので追記です!
https://twitter.com/Anubis_369/status/1203816181582286848?s=19