tokuhirom blog を見て、これ便利だなーと思ったので、試しにこれを使ってprove単位でTest::mysqldを起動するやつを作ってみた。
harriet用設定を作る
まずt/harriet/mysqld.plみたいなのを作る。この中でmysqldの起動とschema流し込みまでしてしまう。複数のdsnを保存しておきたければ、jsonで入れておくと良さそう。
# t/harriet/mysqld.pl use JSON::XS; use Path::Class; $ENV{TEST_EPIC_DSNS} ||= do { require Test::mysqld; my $mysqld = Test::mysqld->new( my_cnf => { 'skip-networking' => '', # no TCP socket 'default-storage-engine' => 'innodb', } ) or die $Test::mysqld::errstr; $HARRIET_GUARDS::MYSQLD = $mysqld; # schema流し込み my $socket = $mysqld->my_cnf->{socket}; system "mysqladmin -uroot -S $socket create sample_test"; system "mysql -uroot -S $socket sample_test < db/schema.sql"; system "mysqladmin -uroot -S $socket create user_test"; system "mysql -uroot -S $socket user_test < db/user.sql"; my $dsns = {}; $dsns->{sample} = $mysqld->dsn(dbname => 'sample_test'); $dsns->{user} = $mysqld->dsn(dbname => 'user_test'); encode_json($dsns); };
以下の点に注意した。
テストでharrietで設定したdsnを読み込む
さらにテスト側ではこの環境変数からdsnを読み込むようにします。
# t/sample.t use DBI; use JSON::XS; my $dsns = eval { decode_json($ENV{TEST_EPIC_DSNS}) } || {}; my $dbh = DBI->connect($dsns->{sample}); # Some tests...
あとはproveのPluginでharrietを呼び出すだけ。簡単ですね。
$ prove -PHarriet=t/harriet/ t/sample.t
まとめ
今回の設定をしておけば、テストを並列に走らせてもプロセスごとにmysqldが立っているのでDB周りでコンフリクトすることがなくなって便利ですね。あとはjenkinsなどで並列に動かせばそれなりに速く動いてくれそうです。
こういうの面倒だなーと思っていたけどHarriet使ったら一瞬でできたので便利ですね。