Perl の標準的なテストスクリプトを実行するためのモジュール。 Perl モジュールのリグレッションテストで使用する。
テストスクリプトは TAP (Test Anything Protocol) にしたがってテストの数やテスト結果を標準出力に出力しなければならない (Test::Harness::TAP 参照)。
Test::Harness に対応したテストスクリプトを作成するためのモジュールとして
などがある。
Test::Harness には prove というコマンドラインツールが付属している。 prove コマンドを使用すると指定したテストスクリプトを実行することができる。
テストスクリプト test.pl を実行する:
prove test.pl
ディレクトリ t の中のテストスクリプト群 (*.t) を実行する:
prove t
prove + テストスクリプトでは Perl モジュールに限らずその他のプログラムのテストにも利用することができる。 例えば C++ で作成したコマンドラインドプログラムの出力をチェックするようなリグレッションテストを Perl スクリプトとして作成してテストするのに使うことができる。
prove --directives
と --directives オプションを指定する。
ExtUtils::MakeMaker によって作成された Makefile を用いて
make test
を実行した際も Test::Harness が使用される。
't' サブディレクトリ以下にテストスクリプトがある時、
prove --blib t
で、make test とほぼ同様のテストが実行される。
ここで make test の場合は ExtUtils::Command::MM の中で blib/lib と blib/arch が @INC に追加された上で Test::Harness::runtests が実行される。このため環境変数PERL5LIBにこれらがセットされた上で、テストスクリプトが実行されるためその子プロセスでも blib/lib や blib/arch からモジュールがロードできるようになっている。
一方 prove の --blib や -I オプションで指定したものは $Test::Harness::switches に設定されて、テストスクリプト実行時にオプションとして使用される。このため子プロセスにはそのパスが引き継がれない)。
一昨日 Scheme で書き始めたのだが、やはり不慣れな言語でTDDをやってみるのも大変。
ということでPerlでやってみる。やはり最初はこちらの方が楽。 Perl では「これだ」という xUnit が無い。
WiKicker は Test / Test::Harness を使用する標準的なテストを採用しているが、fixture の処理が面倒に感じている。 なので何か良い xUnit が欲しいのだが、テストのためだけに要求モジュールを追加するのもよろしくないので簡易的なものを自作するのも悪くないかも。
TDDはリズム感があって良いな。 まだリファクタリングフェーズでどの程度リファクタリングしてから、次のレッドフェーズにはいるかの匙加減がまた掴みきれていない。
Test::Harness モジュールに、単独で Test::Harness 用のテストファイル(群)を実行できる prove というツールがついているのを発見。
スクリプトのちょっとしたリグレッションテストを書いたりするのにこれはいい。 ダミーのパッケージを作る(autoconfiscate するとか Makefile.PL 作る)とか、自前でスクリプトを書くとかしないで済む。書きなれたスタイルでテストコードが書けるし。
tpage (Template Toolkit) 用テンプレートをいじる時にリグレッションテストをかけられるようにしたかったで、使ってみることにする。
CGI プログラムを書いていて、いつも困るのがリグレッションテスト。
パッケージのビルド時に実行するテストスーツ (make check / make test 用テストプログラム群) に含めておきたいが、さすがにその場で Web サーバの下へセットアップするわけにもいかない。 ミニ Web サーバを同梱してテストスーツ内で起動する方法はちょっとおおがかかりだし、ポート番号の選択やらサーバの停止の問題もあって、かなり面倒。
結局、テストスーツの中で環境変数や標準入力など CGI リクエスト環境をセットアップして、CGI プログラムを実行するという王道(?)かつ泥臭いテストを書くことになったりする。
何かいいものはないかと探していたところ、WWW::Mechanize::CGI というものをみつけた。
LWP::UserAgent を継承した WWW::Mechanize モジュールは Web ブラウジングを容易にする有名どころのモジュールである。
WWW::Mechanize::CGI モジュールはさらにこれを拡張したモジュールで、HTTP リクエストを、仮想的に CGI プログラムやサブルーチンへの呼出しにしてくれる。 これを用いるとあたかも Web サーバ上の CGI プログラムにリクエストしレスポンスを受けとっているかのように、テストプログラムを書くことができる。
素晴しい。
さっそく WiKicker のテストを書き換えてみた:
use Test::More tests => 2; use WiKicker::WikICGI::Controller; use WWW::Mechanize::CGI; use File::Temp qw(tempdir); use File::Spec; my $www_dir = tempdir(CLEANUP => 1); my $mech = WWW::Mechanize::CGI->new; $mech->cgi(sub { $ENV{PATH_INFO} = '' if $ENV{PATH_INFO} eq '/'; WiKicker::WikiCGI::Controller->new->run}); $mech->env($mech->env, SCRIPT_FILENAME => File::Spec ->catfile($www_dir . '/wiki'), SCRIPT_NAME => '/wiki'); my $response = $mech->get('http://localhost/wiki'); ok($response->is_success); like($response->content, qr|<title>WikiForum\[WiKicker\]: FrontPage</title>|);
WWW::Mechanize::CGI オブジェクトを new した後、cgi メソッドで CGI サブルーチンを指定するか、cgi_application メソッドで外部 CGI プログラムを指定する。 ここでは直接、CGI サブルーチン (WiKicker::WikiCGI::Controller->new->run を実行)を指定した。
なおここで WWW::Mechanize::CGI が使っている HTTP::Request::AsCGI 0.5 における PATH_INFO の扱いが Apache などとは違って、空でも必ず '/' が入るようになっている。 これだと WiKicker では困るので、サブルーチンのところで修正している。
後は必要ならば WWW::Mechanize::CGI::env で、追加の環境変数設定を行っておく。
セットアップが済めば通常の WWW::Mechanize と同様に get 等でリクエストを行いレスポンスを受けとることができるようになる。
いい。しばらく試してみて不具合がなさそうなら、定番のテストスタイルにしたい。
ちなみに Test::Harness 用の Test::WWW::Mechanize にあわせて、Test::WWW::Mechanize::CGI というものもある。 これらを用いるとさらにテストを書くのが楽になるが、依存するモジュールも多いので無理に使わないほうがいいかもしれない。
ちょっとした文字列構文解析関係の C++ コードを書き始めた。 C++ は随分触ってなかったので「C++ で書き直すのを考慮してそれっぽく Perl で書くから後で書き直して」と最初は言っておいたのだが、それもあんまりだと思って C++ で書くことにした。
Debian GNU/Linux 上で書くので GNU Automake + CppUnit で。 「Perl + Test::Harness」や「Java + Eclipse + JUnit」や「C# + Visual C# + NUnit」などと比べるとやっぱりタルいな。
1つメソッド書くのに、
と 4ファイル5カ所編集しなければならない。 クラス追加時には Makefile.am にヘッダファイルとソースファイルをテストケース用のと含めて4ファイル書き加える必要があるし。
あー面倒。
でも C++ で書き始めると楽しいんだよなあ。
Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。
nDiki は1999年1月に始めたコンピュータ日誌を前身とする Naney の Web 日記(兼パーソナルナレッジベース)です。ちょっとしたノートは nNote にあります。
※内容は個人的見解であり所属組織とは関係ありません。