データベースのテストってみんなどうやってるんだろ?
最近のお仕事の話 - tsucchiの日記の続きみたいなお話。
あともう一つ思ったのが、「DBのデータを使うようなテストって、みんなどうやってやってるんだろ?」ってこと。
この疑問がいまだに解消していないのです。。。
DB を使う Web アプリって、同時にテスト流すとおかしくなるよね?
Apache のプロセスは Apache::Test を使えばユーザ毎とかに分けるとかできそうだけど、DB はそういうモジュールないし。あったとしても、マスタデータとかどうすんねん?みたいな問題もあるから、結局 DB は1個しか持てないんだろうなぁ。
で、DB が1個しかないから、テストデータを流すときに主キーがかぶってエラーになったり、ゴミデータが残って、それが外部キー制約とかあったりして消せなくて、次のテストデータのロードでエラーになってこけたり。とにかく同時にテストを流すとめちゃくちゃになるんですよ。(つーか最初は「不思議なエラーが時々起こるなぁ」ぐらいに思ってた。「誰かが同時にテストを流してるからだ」って気づくのには結構時間がかかった...)
で、いろいろ考えたんだけど、幸いにして、ウチのプロジェクトではテスト用の専用モジュールを作っているから、テスト用モジュールの中で排他制御しちゃうのが一番いいのかな、とか思ったり。
こんな感じ。
排他制御
package Test::MyProject::Util::Mutex; our $lockfile; our $LOCK; BEGIN { $lockfile = "/tmp/test_myproject_util_mutex.pm"; open( $LOCK, '>', $lockfile); flock( $LOCK, 2 ); } END { # flock( $LOCK, 8 ); close( $LOCK ); }
2009/4/22 追記
昨日は unlink をしていましたが、unlink しちゃうとうまく動かないみたいです。あと、flock のロック解除はしてもしなくても良いみたい。
テスト用のモジュール
でっち上げですが、入力チェック用モジュール(InputChecker)と出力チェック用モジュール(OutputChecker)があるとします。
package Test::MyProject::InputChecker; use Test::MyProject::Util::Mutex; #...
package Test::MyProject::OutputChecker; use Test::MyProject::Util::Mutex; #...
テストコード
# ... use Test::More tests => $num_tests; use Test::MyProject::InputChecker; use Test::MyProject::OutputChecker; # InputChecker や OutputChecker を使ってテストを行う # ...
コレを思いついたのは、「帰ろうかな」と思った10分前だったので、実施は明日にでも。
つーかすごく車輪の再発明な気がするんだけど。誰かの作ったもっといいモジュールとか、もっといい方法は無いのかなぁ???