tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

データベースのテストってみんなどうやってるんだろ?

最近のお仕事の話 - tsucchiの日記の続きみたいなお話。

最近のお仕事の話 - 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分前だったので、実施は明日にでも。
つーかすごく車輪の再発明な気がするんだけど。誰かの作ったもっといいモジュールとか、もっといい方法は無いのかなぁ???