mysqldを使ったモジュールのテストに便利なTest::mysqld
mysqldを使ったモジュールを開発する場合にテストのためだけにmysqlをセットアップするのは馬鹿げていますよね。 そこでモジュールのtest時にmysqlを自動で実行してくれる便利モジュール Test::mysqld を使ってみます。
Test::mysqldをtestスクリプトのプラグインとして利用するようにするだけでモジュールのテストやインストールするためだけにmysqlを設定・起動・停止など手動で行う必要はなくなります。
Test::mysqldを使えるようにする準備
Makefile.PL の修正
make test で prove コマンドを叩いてくれるように Makefile.PL に以下を追加します。
Makefile.PL
sub MY::test_via_harness {
"\tprove -r t"
}
プラグインモジュールの指定
prove 実行時に自動的にhookしてくれるプラグインモジュールを指定する。ここでは MyTest::mysqld モジュールをプラグインとして利用するように指定しています。またプラグインは複数指定することも可能です。
.proverc
-Ilib -P MyTest::mysqld
プラグインモジュール MyTest::mysqld を書く
このモジュールは上で.provercでプラグインとして指定したモジュールで proveコマンドから自動的に実行されます。 内部でTest::mysqldをロードすることでデータベースであるmysqldを起動させています。 またこのインスタンスが消滅すると自動的にmysqldもシャットダウンされる仕組みになっている。 mysqldに接続するためのプロパティは $MYSQLD->dsn から取得することが出来この値は $ENV{TEST_DSN} にセットされるため他のモジュールやスクリプトでは $ENV{TEST_DSN}からその設定を読み取ることも可能となります。 この MyTest::mysqld をインストールするかperlの読み取れるpathにセットすれば準備okです。
package MyTest::mysqld;
use strict;
use vars qw($VERSION);
$VERSION = '0.01';
use Test::mysqld;
use Test::More;
my $MYSQLD;
sub load {
if ( my $dsn = $ENV{TEST_DSN} ) {
diag "TEST_DSN explicitly set. Not starting MySQL";
return;
}
$MYSQLD = Test::mysqld->new( my_cnf => { "skip-networking" => "" } )
or plan skip_all => $Test::mysqld::errstr;
$ENV{TEST_DSN} = $MYSQLD->dsn;
# warn $ENV{TEST_DSN};
}
END { undef $MYSQLD }
1;
使ってみる
あとは自分で書くモジュールにmysqldに接続する部分へのパラメータを $ENV{TEST_DSN} から読み込んだ @dsn を接続パラメータとして渡してあげればおkで す。
あとは単に make test を実行するだけで自動的にMyTest::mysqldをプラグインとした proveが実行されmake testの実行中のみmysqldが起動しmake test が終了すると自動停止します。
以下の例はDBIx::Classを使ったSchema クラスで利用した時のものです。
package FugaDBSchema;
use strict;
use warnings;
use base 'DBIx::Class::Schema';
__PACKAGE__->load_namespaces;
our $VERSION = '0.01';
my @dsn;
if ( $ENV{TEST_DSN} ) {
@dsn = $ENV{TEST_DSN};
} else {
@dsn = $ENV{FUGA_DSN};
}
__PACKAGE__->connection( @dsn);
1;
生のDBIを使うときは以下のようになると思います。
my $dbh = DBI->connect( $ENV{TEST_DSN} );
参考)
http://perl-users.jp/articles/advent-calendar/2011/test/18