Test::Module::Used の話
YAPC::Asia も近いので、久々に Perl の話を書こうと思います。僕が作った Test::Module::Used の話。とはいえ、新しい話は特に無いので、今までのまとめをしようと思います。
これは何?
CPAN モジュールを書く際、Makefile.pm に、依存するモジュールを requires, テストで使うモジュールを test_requires に書きますが、往々にして書き忘れることがあります。また、逆に use していないのに、requires/test_requires に指定してしまうことがあります。
このモジュールはそういった「依存指定漏れ」や「過剰な依存指定」を見つけるのに使います。
前にも書きましたが、Test::Dependenciesというモジュールが大体同じ機能を持っているらしいです。(つーかこのモジュールを参考に改良を加えたものです)
使い方
CPAN レイアウトにして、テストコードを置くディレクトリに配置します。僕は module_used.t というテスト名にしています。author_tests 用のディレクトリ(xt)に置くのがいいと思います。(これ自身は依存するモジュールが結構多いため)
典型的な使い方は、
#!/usr/bin/perl -w use strict; use warnings; use Test::Module::Used; my $used = Test::Module::Used->new(); $used->ok;
こんな感じ。これでほとんどのケースは対応できるはずです。
チェック対象からはずしたいモジュールがある場合、
use strict; use warnings; use Test::Module::Used; my $used = Test::Module::Used->new(); $used->push_exclude_in_libdir( qw(Some::Module) ); $used->push_exclude_in_testdir( qw(Test::SomeModule) ); $used->ok;
のようにします。Makefile.PL(META.yml)で Some::Module, Test::SomeModule を書かずに、lib ディレクトリ内で、Some::Moduleが使われていてもテストが成功し、test のディレクトリ(t)で、Test::SomeModule が使われていてもテストが成功します。(意図的に指定漏れさせることができます)
Makefile.PL(META.yml)側の依存指定を無視したい場合、コンストラクタで指定します。
use strict; use warnings; use Test::Module::Used; my $used = Test::Module::Used->new( exclude_in_build_requires => [qw(Module::AA)], exclude_in_requires => [qw(Module::BB)], ); $used->ok;
とすると、Makefile.PL(META.yml) のbuild_requires に Module::AA が指定されていて、実際に使われていなくても、そして requires に Module::BBが指定されていて、実際に使われていなくてもテストが成功します。(意図的に過剰に指定させることができます)。
基本的な動作
MATA.yml から requires, build_requires を引っこ抜いて、依存指定されたモジュールをリスト化します。モジュール側からは、lib, t をスキャンして、lib 配下の .pm と t 配下の .t と .pm を抜き出して、そこで use されているモジュールを抜き出します。このとき、コアモジュールと、lib/t 内で package 宣言されたモジュールは除きます。で、META.yml のリストと、スキャンしたモジュールのリストをつき合わせて、差異がないかをテストしています。
うまく扱えないモジュール
ほとんどのモジュールはデフォルトでテストできると思いますが、駄目なパターンがいくつか分かっています。
サブモジュールを持っているものを use している場合
Test::Module::Used でやりたいのだけど、できないことでも書いたのですが、DBIx::Skinny みたいに、サブモジュールを持っているモジュールを use している場合は使っているサブモジュールを全部 Makefile.PL(META.yml)で指定してあげないとうまく動きません。(もしくは、exclude 系を調整する必要があります)
Test::Module::Used 側で、CPAN(やその他のモジュール情報を提供してくれるサービス)に問い合わせることで、対応出来なくは無いのですが、環境依存でテストが通ったり通らなくなったりするのは嫌だし、サブモジュールが独立することもあったりすると思うので、当面このままにしておこうと思っています。
今後について
大体作りたいものは出来ているのですが、時間があれば Catalyst::Plugin 対応とかやってみようかな、と思っています。あと、テスト対象を絞れる(「依存漏れだけチェック」、とか「lib は見るけど t は見ない」とか)できると嬉しいのかな、と思います。