― Web Technology and Life ―

PerlでTDD(テスト駆動開発)するなら覚えておきたいCPANモジュール群

2012-08-02
最近、久しぶりに新規コードを書いたんですが、そのテスト書く中でTest::Mock::Guardってモジュール使って便利だったんで、ここらで、動作確認テストを書く上でいいな(使ってみたいな)って思ったモジュール群やテスト関連ネタを個人的なメモとしてまとめておきたいと思います。

いいなって思うPerlの動作確認テスト系CPANモジュール群

私が実際に普段使っているものから、これいいなー使ってみたいなーと思うものまで、一覧にまとめて見ました。結構いろんなモジュール使わないと、いい具合にTDDってできないものだと思います。

入門編

モジュール名 概要 参考日本語記事
Test::More 言わずと知れた基本モジュール。まずはこれから perl でテストを始めよう!!
Test::Harness/prove テスト群一式を一括実行する。.provercでオプション使うと更に便利♪ prove についてのおさらい,テストのためにデーモンを自動的に起動するやりかた2011年版,高速なWeb APIの実装とテスト、後述

proveのごにょごにょしたのは、おいておいて、とりあえず、Test::Moreで動作確認して、prove -I ./lib ./t/*/.tとかで一括実行することを覚えておきたいですねっ!

覚えておくと便利編/(かゆいところに)

モジュール名 概要 参考日本語記事
Test::Pretty Test::Moreでsubtestを使ったネストするとテスト結果の表示が見づらくなるけど、見やすくしてくれるモジュール Test-Pretty - Prettify the Test::More's output(日本人の記事w)
Test::Warn warnの文字列をキャッチ。きれいにかけるから気持ちよい Test::Warn - perldoc.jp
Capture::Tiny Test::WarnやTest::Outputだと、system関数で呼び出したり、Plack::TestでのWebアプリ上の警告をチャッチできないけどCapture::Tinyだとできるのです!! 標準出力や標準エラー出力を捕まえてテストする Test::Output / Capture::Tiny
Test::Deep 具体的な値でなく、複雑なhashref,coderefとかのデータ構造をテスト 後述、型一致ベースのテストに使えるPerlモジュール ~Test::Deep::Matcher,MouseX::Types~
Test::Deep::Matcher Test::Deepと合わせて使いたい 後述、型一致ベースのテストに使えるPerlモジュール ~Test::Deep::Matcher,MouseX::Types~
Test::Mock::LWP::Conditional 特定のURLのレスポンスを偽装。APIなどHTTPを含むテストに便利。 HTTP通信を含むモジュールのテスト #2
Test::Mock::Guard 既存クラスの挙動をオーバーライド。インターフェイス的クラスのテストに便利。 Test::Mock::Guard Released,後述
Test::MockObject Test::Mock::Guard以上にいろいろなことができる複雑っぽい 今のところ日本語で見当たらない
Test::MockTime localtimeとかを偽装できる Test::MockTime - 時間にまつわるtest
Test::Attribute::AutoLevel テストコードを共通化するときに便利 use Test::Attribute::AutoLevel
Test::Synchronized テストの並列実行をするとき、「一部だけ同時に走らせたくない」というのに便利 高速なWeb APIの実装とテスト
Text::Xslate->validate Text::Xslateのvalidateメソッド使うとxslateのテンプレートのSyntaxチェックができる!!! Text::XslateにテンプレートのSyntaxをチェックするメソッドが追加されて便利

いろいろな動作を確認したくなってきたときに、助かるのがこれらのモジュールです。他にもいろいろ「これいいよっ!」っていうのがあったら是非教えて頂きたいのですが、私はこのあたりを使って結構助かっています。

覚えておくと便利編/(ミドルウェア連携)

モジュール名 概要 参考日本語記事
Plack::Test PerlのPSGIアプリの低レイヤーのテスト。404をかえすとか302をかえすとか、基本的なHTTPのやり取りが可能 Plack::Test でアプリケーションをテストする
Test::WWW::Mechanize::PSGI PSGIアプリのテストに使える。とくにWWW::Mechanize風にフォームとかのテストが書きやすい。JSがからんでくると無理だけど、そういう場合はSelenuim::Remote::DriverとPhamtomJSを使う PSGI な webapp の複雑なテストには Test::WWW::Mechanize::PSGI
Test::mysqld MySQLを使ったテストに便利。 Perl のテスト用に MySQL 環境を自動で構築するモジュール Test::mysqld を書いた,高速なWeb APIの実装とテスト,テストのためにデーモンを自動的に起動するやりかた2011年版
Test::PostgreSQL Test::mysqlのPostgreSQL版らしい。メンテナーがkazuhoさんから別の人にうつって、 大文字になったっぽい? Perl のテスト用に PostgreSQL のインスタンスを自動で構築するモジュール Test::postgresql を書いた
Test::TCP 特定のミドルウェアをかませるテストで使う。 それ Proc::Guard 0.04 でできるよっていう話,高速なWeb APIの実装とテスト
Proc::Guard Test::TCPと合わせて使いたい。立ち上げたプロセスはテストが終われば自動的に消えるようにできる。 それ Proc::Guard 0.04 でできるよっていう話,高速なWeb APIの実装とテスト
Test::RedisServer Redisを使ったテストに使えるみたい Test::RedisServer ってのを書いた
- モジュールじゃないけど、メールのテストをしたいときの参考 Perl5 によるメール送信 - 実践的な Email::Sender の利用方法

この前、makamakaさんにTest::PostgreSQLがあるというのを聞いたので、検索してリストに入れておきました。この記事をポチポチ書いているときに、Test::RedisServerが出たので入れました。いろんなミドルウェアがあるから、まだまだたくさんある気もしますが、基本はTest::TCPでがんばればなんとなく気がします。

崇高なTDDに向けて編

モジュール名 概要 参考日本語記事
Devel::Cover テストのカバレッジを出してくれる テストのカバレッジを出す ,Devel::CoverとJenkins
Test::Perl::Metrics::Lite コードの複雑でない程度をチェックしてくれるらしい Test::Perl::Metrics::Liteでコードの”死活”監視,Perl::Metrics::LiteのCLIでPerlモジュールのメトリクス測定
Test::Perl::Metrics::Simple Test::Perl::Metrics::Liteと同系統。違いはよくわからん。 Perlのメトリクス計測Jenkinsで継続的メトリクス測定のすすめ
Test::Perl::Critic コードがきれいか『Perlベストプラクティス』を元にチェック Test::Perl::Critic で PBP 準拠なコードを自動テスト

Devel::Coverをちょっと使ったことあるくらいで、このあたりは個人的に積極的に使ってみたいなーというものばかりなので、よくわかっていないっす(苦笑)。とくに、コードの保守関連の、Test::Perl::Metrics::Lite、Test::Perl::Metrics::Simple、Test::Perl::Criticの使い分けみたいなのをしっかり調べようかなーと思っているのですが、すでに知見があるからいらっしゃいましたら、そのあたり伝授して頂けるととてもハッピーですっ!

番外編/CI(継続的インテグレーション)

モジュール名 概要 参考日本語記事
Ukigumo 一部CPANにない。CI(継続的インテグレーション)をどちらか気軽にできる PerlのUkigumoでCIをはじめようとしてみた
Jenkins Perlモジュールではない。CIだと最近はJenkinsらしい。Devel::Coverと連携などいろいろできるらしい 3分でPerlのプロジェクトをJenkins Readyにする
App::ExtractUsed Makefile.PLを後からつくるときに助かります。まだGithub App::ExtractUsed というものを書いている話
carton モジュール依存管理ソフト。テストする環境を変えたい時に、依存モジュールを一気に落とせる仕組みづくりができる。 Carton使ってみた

このあたりもちょっと触ってみたか、いいなーと思っているだけのものたちですねー。なかなか業務に導入するきっかけが作れず・・・。

特にシェアしたいテスト系モジュールの使い方

ホントはすべてのモジュールのサンプルを書こうと思っていたんですけど、やたら多くなったので、最近いいなって思ったモジュールや、なんか日本語の紹介記事見かけないなってモジュールを、を詳細に書きたいと思います。

Test::Mock::Guardの使いどころ

一つのクラスがいくつかの同じインターフェースのクラスを使うっていうコードがあると思いますが、そんなときにめちゃくちゃ便利です。

たとえば、以下のようにMyInterfaceClassってコード書きたいんだけど、MyInterfaceClass::A8ってコードに依存していて、とりあえず、 MyInterfaceClassのコード書いたんだけど、MyInterfaceClass::A8ってコードは書いていない場合みたいな感じです。

こんな感じ、もろもろ空気を察してください。

use Test::More;
use Test::Mock::Guard qw/mock_guard/;
use MyInterfaceClass;
use MyInterfaceClass::A8;

my $today = '2012-07-24';

my $guard = mock_guard( 'MyInterfaceClass::A8', +{
    login          => sub {},
    monthly_sales  => 1000,
} );

api('MyInterfaceClass')->work(
    asp         => 'a8',
    check_month => '201208',
);

is $db->('monthly_sales',{ term => '201208'})->sales, 1000;

done_testing;

うーん、あまり参考にならない例になってしまいましたね。。。いい例を思いつきたいところ・・・。

Test::Deep

なんか、ハッシュリファレンスが返ってくるんだけど、その中身はなんでもいいっていうテスト書きたくなったりしませんか?そんなときに最高なのが、このTest::Deepです。

use Test::More;
use Test::Deep;

my $hashref = +{
    name => 'hirobanex',
    area => +{
        address  => 'Tokyo',
    },
    social => {
        is_facebook => 1,
        is_ameblo   => 0,
    },
};


cmp_deeply $hashref,+{
    name => ignore(),
    area => +{
        address  => ignore(),
    },
    social => {
        is_facebook => ignore(),
        is_ameblo   => ignore(),
    },
};

done_testing;

Test::Deepを使って型チェックみたいなのもできますが、MouseX::Types::MouseをTest::Moreとコンビネーションさせる方法もあります。

use Test::More;
use MouseX::Types::Mouse qw/:all/;

my $str = 'hogehoge';
my $age = 23;


ok is_Int($age);
ok is_Str($str);

done_testing;

さらに、コンビネーションさせて、こんなこともできます。

use Test::More;
use Test::Deep;
use MouseX::Types::Mouse qw/:all/;

my $hashref = +{
    name => 'hirobanex',
    area => +{
        address  => 'Tokyo',
    },
    social => {
        is_facebook => 1,
        is_ameblo   => 0,
    },
};

cmp_deeply $hashref,+{
    name => code(\&is_Str),
    area => +{
        address  => code(\&is_Str),
    },
    social => {
        is_facebook => code(\&is_Bool),
        is_ameblo   => code(\&is_Bool),
    },
};

done_testing;

Test::Deepの便利関数は、ignoreと、subhashofとかと、array_eachと、codeあたりが便利だと思って使っています。よくわからん、というときは、全部codeとMouseX::Types::Mouseでやっつけます。MouseX::Types::Mouseについては、また追記するか、参考URLを探します。【追記】で、いろいろ書きましたが、わかりづらいだろうし、ありがたいことにikasam_aさんに「Tes::Deep::Matcherを書いたよ」ってご紹介頂いたので、こちらに詳しく書きました→『型一致ベースのテストに使えるPerlモジュール ~Test::Deep::Matcher,MouseX::Types~』、あわせてご覧頂けるとうれしいですー。

proveをハックする

参考記事をまとめて、こんな感じでやった的なことを書こうと思ったんですが、わりとめんどくさいし、まぁ参考記事以上のものにはならないなと思ったので、やめました。笑。気になる人がいれば、追記します。とりあえず、xaicronさんとlestrratさんの記事はほんとに参考になりまくりですっ!

とても参考になるPerlのテスト系Tips集一覧

CPANモジュールという観点ではなく、広い意味でテストに役立ちそうな情報のまとめです。

とりあえず、この記事はPerl Advent Calendar Japan 2011 Test Trackのまとめ直しかというくらい、Perl Advent Calendar Japan 2011 Test Trackから参考にしています。ホント感謝です。

Yapc::Asia2012のトークに応募しています

Perlの最大のイベントYapc::Asiaが今年も開催されますが、今年はトークに応募してみました。バッチ処理とかジョブキューシステムとのQudoとかについて普段やっていることをまとめて発表する予定です。ご興味ありましたら、是非『不安定な環境の中でのバッチ処理~JobQueueシステムQudoを使った事例~』に「いいね!」とかくださるとうれしいですー!よろしくお願いしますっ!!

最後に

やたら、「それは違うよ!」とか、「こんな便利なものあるよっ!」とか、いろいろあれば、Twitterやはてぶコメントでどしどしフィードバック頂けるとうれしいですっ!久しぶりに勉強会ネタ以外を記事にできたことに感無量!実は、Hachioji.pmのLTに準備しておいたんですが、疲労困憊でLTできずお蔵入りしそうになったので、加筆してブログの記事にしましたー笑。

Perl update_at : 2014-05-10T14:19:26
hirobanex.netの更新情報の取得
 RSSリーダーで購読する   
blog comments powered by Disqus