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

created:

Back to top