D-7 <altijd in beweging>

Day to day life of a Perl/Go/C/C++/whatever hacker. May include anything from tech, food, and family.

タグ:Test::mysqld

以前ここで書いたTest::mysqldの仕組み、すこーしずつ毎回変えながら使ってる。今は継承はしてないが、まぁやってることはだいたい一緒。

で、テーブルのインデックスとか使ってるクエリとかを確認したいなーと思って、slow query logと general log をぼこっと出せるようにした。

    if (! $ENV{ TEST_DSN }) {
        my %my_cnf = (
            'skip_networking'     => '',
        );

        if ( $ENV{SLOW_QUERY_LOG} ) {
            $my_cnf{ slow_query_log } = 1;
            $my_cnf{ slow_query_log_file } = $ENV{SLOW_QUERY_LOG};
            $my_cnf{ long_query_time } = $ENV{SLOW_QUERY_TIME} || 0.1;
        }
        if ( $ENV{GENERAL_QUERY_LOG} ) {
            $my_cnf{ general_log } = 1;
            $my_cnf{ general_log_file } = $ENV{GENERAL_QUERY_LOG};
        }
        my $mysql = Test::mysqld->new(
            my_cnf => \%my_cnf,
        );

        if (! $mysql) {
            confess "Could not establish mysqld";
        }

        $ENV{TEST_DSN} = $mysql->dsn();
        $self->{_mysql} = $mysql;
    }
一回もう少しハードコードに近い形にしてみたんだけど、テストなので環境変数が一番楽だという結論にいたった。使うときはこんな感じ。ログの位置を絶対パスにしないと Test::mysqldが閉じると同時に消されるディレクトリに書き込まれるので要注意。

    SLOW_QUERY_LOG=`pwd`/slow_query.log \
    GENERAL_QUERY_LOG=`pwd`/general_query.log \
        make test
    このエントリーをはてなブックマークに追加 mixiチェック

[2010/10/21 追記] Makefileいじらないでもいいようなモジュールが出てますのでこちらの新しい記事もどうぞ



Test::mysqldを使うとクールにMySQLを起動させられるので、それを使おうとしたんだ。でもおいらのローカルにあるmysqlをMacPortsのmysqlで、ファイルレイアウトがメタメタなんだ。だからまずこんな感じで、Test::mysqldを継承するMyApp::Test::mysqldを書いたわけさ!

必要とあればMacPortsとかの環境じゃなくてもMYSQL_INSTALL_DBとMYSQLDを設定すればテスト時にTest::mysqldが見るバイナリを変更できるのがミソだね!

さて、これを使っても、何個もテストスクリプトがある時に一回一回mysqlを立ち上げ直してちゃ意味がない。遅いし、毎回DBの設定をしなくちゃいけないじゃないか!

だもんで、まずmake testが走るときに前もってTest::mysqldを起動させ、make test 終了とともにDBが停止するような仕組みをMakefile.PLに書いてみたわけさ!


Oh, how very unpleasantly hack-ish!

汚いけど、これでMakefileをいじっちゃうわけだね!ちなみにModule::Installも同じような力業でMakefileを編集してるよ!

ともあれこれでmake testとした時に自動的にMyApp::Test::mysqldが立ち上がるってわけさ。$SIG{INT} = \&exitってしておくのは、ユーザーがCtrl-Cした時にTest::mysqld::DESTROY()が走るようにするためのおまじないだよ!

mysqldが立ち上がったら、そこへの接続情報を$ENV{TEST_DSN}につっこんでおくわけさ。これでテスト側からこの値を参照するだけでDBに接続できるわけだね。

ここまで来たらもう一歩!

  • DBIx::Classを使ってるんだから、DBスキーマも自動的にdeployしたいじゃない!
  • それぞれのテストでTEST_DSN呼んだりするの面倒くさいよね!
  • 単体のファイルを実行した時は、mysqld起動+deployを各ファイルでやってほしいけど、make testの場合は1回だけ実行したい!

こんなワガママなキミはそれ用のラッパーを作ると便利かもね!そこでこんなMyApp::Testを書いたわけさ(3回目)!

ここでは僕の自家製DIコンテナOrochiってのを使ってるのでわからないことだらけかもしれないけど、重要なのは以下のことさ!

  • MyApp::Schemaは$self->assembler->get('schema/master')とすることにより、すでに生成されているならその値を、そうでなければあらたに生成した値を得ることができる。
  • MyApp::Schemaの生成には 'schema/master/connect_info'というデータが必要
  • connect_infoのDSN部分は、$ENV{TEST_DSN}が設定されているなら、それを利用する(mysqldはMakefileによって起動している)が、そうでないなら、自分でmysqldを立ち上げる。
  • その際、空のデータベースを立ち上げただけでは意味がないので、deployフラグもつけておく
  • deployフラグがたっている場合は、DIコンテナからschemaを取り出す際にdeployもしてしまう
こんなことをしておけば、make test時に一回一番最初だけに実行されるt/000_setup.tみたいなファイルを用意してMyApp::Test->new()->deploy()すればmake test中には一回しか起動+deployはされないし、各テスト実行時にもMyApp::Test->new()しておけばMyApp::Schemaを使用する時に自動的に同じ事が起こるわけさ!

じゃあもう眠いから、アディオス!

    このエントリーをはてなブックマークに追加 mixiチェック

このページのトップヘ