PowerShellでテストすると良いよという話

Windows PowerShell Blog : Why Should I Test With PowerShell?で、PowerShellをテストに使うと良いぜ、という話が出ていて、10個ほど、利点が挙げられてたので訳してみました。コメント欄でもかかれてますけど、僕には具体的にどういうことなのか良く分からないところもありましたが……。

  1. PowerShellの中で、簡単にコマンドラインプログラムが実行できる
  2. テストケース用に、動的にコードを生成したり、テストデータを生成したりできる(これによって、ファジングとか、データ駆動なテストがとっても簡単に)
  3. PowerShellから、COMへ簡単にアクセスできるようになってる
  4. PowerShellC#に埋め込める(なので、フレームワークを書かかずに、単に、基盤へPowerShellを埋め込める)
  5. PowerShellでは弱い型付けの変数を使える
  6. コマンドラインからAPIを試せるので、手動でテストできるし、自動的にも行える
  7. コマンドラインの履歴を参照して、なにについて調査したか確認、それをテストケースに落とし込める
  8. 必要があれば、強い型キャストや、型変換が行える
  9. 追加のテスト情報を提供するのに、verbose、warning、debugストリームがサポートされている
  10. テスト環境を準備、後始末するのに、PowerShellのシステム管理機能が役立つ

細かいところだと、"strongly cast"と"coerce types"の違いがわからんねーとか、"embed PowerShell in your infrastructure"ってどういう事なの、とかは思うんだけど、僕自身最近のPowerShellの用途は仕事で作ったアプリ内のクラスを呼び出してテストしたりとか、一部分を切り出してツールにしたりとか、テスト用にデータの記録とか、なんで、ここに書いてあるのは確かにそうかな、と思います。C#なりVB.NETなりで全部できるといえばその通りなんだけど、コンパイルいらないとか、弱い型付けなんで色々楽だね、とか、C#のソースをエディタの置換とかで量産するとなんかダサい気がするけどスクリプトなら逆に効率的で良いことな印象を受けるとか気分的な点も含めて。
もう一つ、似たような用途なんですが、仕事ではASMXのWebサービスを良く作って/使っていて、ここでWebサービスを使う事自体パフォーマンス的にどうなのよ、とかは思いますが、好きに設計できるわけでもないので黙々とやっており、ログはパラメータをXMLシリアライズして残してたりするんですが、なんか障害でもあった時に、ログからリクエストを切り出して、PowerShellスクリプトで同じ要求を投げてみる、とかを良くやります。WSDL参照して作ったプロキシクラスをDLLに突っ込んでおいて、呼び出すだけなんですけど。こういう感じ。イメージですけどそのままなので……。namespaceごとに、クラス名のところを{0}にした文字列を用意しておくやり方は、『Windows PowerShellクックブック』に載ってました。


# ASMX Webサービスのプロキシクラスを含むDLL
[System.Reflection.Assembly]::LoadFile('c:\work\ws_proxy_desu.dll')
# シリアライズ
[System.Reflection.Assembly]::LoadWithPartialName("System.Xml")

# フォーマットして使う用namespace
$ct = 'Work.Brand.Gyomu.Src.NantokaAPI.{0}'
$xml = 'System.Xml.Serialization.{0}'
$io = 'System.IO.{0}'

# シリアライザ
$slzr = New-Object ($xml -f 'XmlSerializer') -ArgumentList @($ct -f 'REQUEST_PARAM')

# ファイルからデシリアライズ / 引数からとったほうが便利
$fs = New-Object ($io -f 'FileStream') -ArgumentList @('c:\work\req.xml', 'Open')
try { $req = $slzr.Deserialize($fs) } finally { $fs.Close() }

# クライアントプロキシクラスのインスタンス
$ws = New-Object ($ct -f 'WS_Proxy')

# 必要があればURL書き換える
# $ws.Url = ''

# WebMethod呼び出し
$res = $ws.WebMethod($req)