以下のようなCGIプログラムのテストを書きたいとします。
#!/usr/bin/perl use strict; use warnings; use CGI; my $q = CGI->new; my $number = $q->param('number'); unless (defined $number) { print $q->header( -status => 200, -type => 'text/plain; charset=utf8', ); print "Please set number"; exit; } my $result = ''; if ($number % 3 == 0) { $result .= 'Fizz'; } if ($number % 5 == 0) { $result .= 'Buzz'; } $result ||= $number; print $q->header( -status => 200, -type => 'text/plain; charset=utf8', ); print $result;
ロジックが一緒に書かれているので、Test::Moreでテストしづらいですね。 こんなときはCGIプログラムをPSGIアプリに変換し、 Plack::Testでテストすると楽です。
PSGIアプリに変換するにはPlack::App::CGIBinを使って、 以下の内容のapp.psgiを作成します。
#!/usr/bin/perl use strict; use warnings; use File::Basename; use Plack::Builder; use Plack::App::CGIBin; my $basedir = dirname(__FILE__); builder { mount '/' => Plack::App::CGIBin->new( root => $basedir, exec_cb => sub { 1 } )->to_app; };
これでめでたくCGIプログラムはPSGIアプリになりました。 普通のPSGIアプリと同様に、plackupコマンドなどで実行できるようになります。
$ plackup app.psgi
ブラウザなどで「http://localhost:5000/fizzbuzz.cgi?number=1」にアクセスすると実行できます。
PSGIアプリは、Plack::Testでテストすることができます。 先ほどのCGIプログラムのテストは、次のように書くことができます。
use strict; use warnings; use Test::More; use Plack::Test;use HTTP::Request::Common; use Plack::Loader; use Plack::Util (); my $app = Plack::Util::load_psgi('app.psgi'); test_psgi $app, sub { my $cb = shift; my $res; $res = $cb->(GET "/fizzbuzz.cgi?number=1"); is $res->code, '200'; is $res->content, '1'; $res = $cb->(GET "/fizzbuzz.cgi?number=2"); is $res->code, '200'; is $res->content, '2'; $res = $cb->(GET "/fizzbuzz.cgi?number=3"); is $res->code, '200'; is $res->content, 'Fizz'; $res = $cb->(GET "/fizzbuzz.cgi?number=4"); is $res->code, '200'; is $res->content, '4'; $res = $cb->(GET "/fizzbuzz.cgi?number=5"); is $res->code, '200'; is $res->content, 'Buzz'; $res = $cb->(GET "/fizzbuzz.cgi?number=15"); is $res->code, '200'; is $res->content, 'FizzBuzz'; }; done_testing();
書きやすいですね。