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