モダンPerlの世界へようこそ

第22回 Mojolicious::Lite:本当に簡単なウェブアプリがあればいいときは

この記事を読むのに必要な時間:およそ 5 分

Mojolicious::Liteアプリケーションのテスト

いまはブラウザを使って動作確認しましたが,もちろんテストのたびにブラウザを起動するのはばかげた話ですから,自動テストもできるようにしておきましょう。これもやり方は何通りかあるのですが,ここではアプリケーション本体のなかにいきなりテストを書いていく方法を紹介します。このようなパッチをあてたうえで,コマンドラインから「prove -v nopaste」を実行してみてください。

@@ -30,6 +30,27 @@
     $self->stash(code => $file->slurp);
 } => 'page';

+if ($ENV{HARNESS_ACTIVE}) {
+    require Test::More;
+    require Test::Mojo;
+    require File::Path;
+
+    local $datadir = app->home->rel_dir('testdir');
+    mkdir $datadir unless -d $datadir;
+
+    my $t = Test::Mojo->new;
+    $t->get_ok('/')->status_is(200)->content_like(qr/form method/);
+    $t->post_form_ok('/', { code => 'sample text' })
+      ->status_is(302);
+    my $location = $t->tx->res->headers->location;
+    $t->get_ok($location)->status_is(200)
+      ->content_like(qr/sample text/);
+
+    Test::More::done_testing();
+    File::Path::rmtree($datadir);
+    exit;
+}
+
 shagadelic;

 __DATA__

done_testing()というのはTest::More 0.88以降で導入された新しいコマンドです。proveやmake testなどを使って自動テストを実行するとHARNESS_ACTIVEという環境変数が有効になることを利用して,自動テストのときはデータディレクトリを変更しつつ,Test::WWW::Mechanizeに似たインタフェースを持つTest::Mojoを使ってそれぞれのパスに正しくアクセスできるか,フォームから投稿した内容が次のページで表示されているかなどのチェックをしています。

今回のサンプルアプリケーションは小さいので,⁠shagadelic;」でコマンド/サーバに処理を返す直前にテストをまとめて書いていますが,アプリケーションが大きくなってきたらHARNESS_ACTIVEでくくったブロックをいくつかに分割すれば,実際のコードとテストが近い,見通しのよいものになるでしょう。

Mojolicious::Liteと日本語の扱い

先にもちらっと書きましたが,この原稿を執筆している時点でCPANにあがっているバージョン0.999914にはマルチバイトの対応に問題が残っています。最近のMojoはフォームからPOSTされてきたパラメータを自動的にdecodeしてくれるようになっているのですが,このとき,utf-8以外の文字コードを使っていると(たとえばWindows環境でシフトJISを扱うアプリケーションを書こうとすると)⁠POSTした内容が(decodeに失敗した結果)消失してしまうようになっていたのですね。

この問題はリポジトリ上ではすでに対策を取り込んでもらっているので,次のバージョンがリリースされたときには解決しますが,どうしてもいますぐCPAN版を使う必要がある場合はmultipart/form-dataでPOSTすることで問題解決する場合があることも覚えておくとよいでしょう(このあたりの挙動はやや整合性がとれていないので,将来的にはまだ変更の可能性があるかもしれません)⁠

また,Mojoliciousには最近プラグイン/トリガの機構が追加されました。これも次のバージョンで導入される予定ですが,charsetプラグインを使うとレンダリング時やパース時などの文字コードの設定を簡単に書けるようになります。

@@ -8,7 +8,7 @@
 mkdir $datadir unless -d $datadir;

 app->log->level('error');
-app->types->type(html => 'text/html; charset=utf-8');
+plugin(charset => { charset => 'Shift_JIS', encoding => 'shift_jis' });

 get '/' => 'form';

後者のencodingは省略可能ですが,携帯などでContent-Typeに設定するcharsetと入出力時の文字コードが微妙に異なる場合などは明示的にencodingを設定しておくことで文字化けを防ぐことができます(このあたりをもっと動的に変更したい場合はMojolicious::Plugin::Charsetを参考にプラグインを書いてください)⁠

なお,Mojoliciousのテンプレートは,この例のようにアプリケーションに同梱することもできますし,外部のファイルを読み込むこともできるのですが,⁠__DATA__以下の)アプリケーション内部のテンプレートを読み込む場合は(use utf8して)utf-8で,外部のテンプレートファイルを読み込む場合はcharsetプラグインなどで設定した(app->renderer->)encodingの値にあわせた文字コードで記述する必要があることも覚えておいてください(シフトJISで出力するからといってアプリケーションをシフトJISで記載すると化けますのでご注意ください)⁠

外部テンプレートの置き場所はapp->renderer->rootで設定できます。

app->renderer->root('./templates');

外部テンプレートには「@@ page.html.ep @@」のような区切り文字は不要です。

Mojoの現状とこれから

MojoはもともとPerl 5.8.1さえ入っていればあとは何もいらない,FTPなどでも,あるいはWindowsなどでも簡単にインストールできるフレームワークというのがひとつのセールスポイントでしたが,Mojolicious::Liteのアプリケーションも,従来ならCGI.pmを使ってつくっていた一枚もののCGIアプリケーションと同じくらい手軽に書け,アップロードできるようになったという意味で,Mojo(licious)は以前にもまして「⁠FastCGIやmod_perlにも対応した)モダンなCGI.pm」としての性格が色濃くなったといえます。

予定されていたドキュメントの整備についてはまだ進んでいないようですが,ドキュメントを整備してバージョンを1.0にあげてしまったらそれ以上の大規模改修はむずかしくなってしまいますから,その前に,ベータテストでしっかり使い込んで,出せるうみは出しておきたい,という気持ちもあるのでしょう。日頃から生煮えのモジュールを使うことに慣れてしまった人のなかにはベータテスト中の仕様変更に目くじらをたてる人もいますが,あまりに早い段階から使われるようになってしまった結果,途中で問題が出てきてもうかつに仕様変更できなくなって大変な苦労をしている(あるいは古いものを投げ出して新しいものに切り替えてしまう)コミュニティも少なくないことを思えば,この1年のMojoの変化は十分理性的なものだったように思えます。

また,ときどき「Mojoは遅くてだめだ」といった声も耳にしますが,いまのMojoにとって最優先事項はすべてのAPIを固めて,十分なテストを行うこと。APIの設計そのものがおかしいときにいくら高速化をしても,その努力はより適切なAPIが固まった時点で無駄になるのですから,現状では的はずれな批判というしかありません。

本当はこの連載でMojoを取り上げるのはMojoが無事バージョン1.0を迎えてから,と決めていたのですが,巷でMojoの話題が出るたびに「特集記事のコードが動かない」という嘆きの声が聞こえてくるので今回は特集記事のコードを修正するかたわら中間報告をしてみた次第。あらためて書いておきますが,Mojoは現在ベータテスト中です。ベータ版だからといって使えないということはありませんし,実際筆者はさまざまな場面でMojoアプリケーションを書いていますが,まだしばらくは(今回見つけた文字コードまわりの問題のように)不具合が見つかって修正が必要になる場面も出てくる可能性があることは覚えておいてください。

ただし,必要以上にこわがるのはなしですよ。Mojoはやみくもに機能拡張を続けて,どこにゴールがあるのかわからないというモジュールではありません。そこに到達するまでにあとどのくらい時間がかかるかはまだわかりませんが,きちんとバージョン1.0を目指して開発が進められているのですから。

著者プロフィール

石垣憲一(いしがきけんいち)

あるときは翻訳家。あるときはPerlプログラマ。先日『カクテルホントのうんちく話』(柴田書店)を上梓。最新刊は『ガリア戦記』(平凡社ライブラリー)。

URLhttp://d.hatena.ne.jp/charsbar/