Test::Apache2 をリリースした
Test::Apache2 を CPAN にリリースしました。初 CPAN モジュール!焦って 0.02 まで送っちゃったので、そのうち 0.02 が出てくるはず。
これはなに?
Test::Apache2 を使うと mod_perl ハンドラのテストがこんな風に書ける。
use Test::More tests => 1;
use Test::Apache2;
my $server = Test::Apache2::Server->new;
$server->location('/myapp', {
PerlResponseHandler => 'MyAppHandler',
});
my $resp = $server->get('/myapp');
is($resp->content, 'hello world');
まず Test::Apache2::Server という Facade 的なオブジェクトに、テストしたいハンドラ (ここでは MyAppHandler) を登録する。次に $server にリクエストを送ると、対応するハンドラが呼ばれて HTTP::Response が返ってくる。これで、あとはその中身をチェックすればいい。
Apache::Test との最大の違いは Apache のプロセスが起動しないところにある。Test::More とかが use されているのと同じ Perl 処理系のプロセスの中で、
- ハンドラを new して
- Apache2::RequestRec にはコンストラクタがないので、代わりの Test::Apache2::RequestRec を new して
- それをハンドラのインスタンスにわたして
というかたちでテストが進んでいく。
なので速い、けど mod_perl 特有の問題とかはあんまり再現できない。
あるべき設計と中間層のコスト
本当なら、mod_perl ハンドラを
- リクエストをとってレスポンスを返す関数
- それを Apache2::RequestRec とつなぐ関数
と分割しておいて、テストは前者に対して書く、というのがあるべき設計だろう。
ただ、中間層をもうけるには作業的なコストがかかるし、作業が完了しても、それを走らせるところで計算機的なコストがかかる (なにもしないよりは CPU やメモリは食いますよね)。そこらへんを払いたくないけど、テストがないのはないという場合に Test::Apache2 は便利なんじゃないかと思う。
今後
リリースしてみたものの、実際には色々メソッドが足りなかったりする。
Test::Apache2::Server には get があるのに post, put, delete が無いし、Test::Apache2::RequestRec は Apache2::RequestRec にあるメソッドが全部あるわけではないので、しばらくはそういう地味なところを埋めていく予定です。レポジトリは Bitbucket にあります。
Test::Apache2::RequestRec 単体の、new できる Apache2::RequestRec としての使い方ももうちょっと考えたいなあ。Google Testing Blog には
This highly-focused fake is easy and quick to write, and makes the test much simpler and more readable.
とあって、Test::Apache2::RequestRec は highly-focused ではないんだけど、実際に Apache2::RequestRec を Test::MockObject でちまちま作るのはすごいだるいので、そういう場面も救えるようにしたい。