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

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

データベースのテストの話

最近のお仕事の話とかデータベースのテストってみんなどうやってるんだろ?の続きみたいな話。

マーチン・ファウラーが Thought Works における、Ruby での開発について色々書いてます。(記事が書かれてすぐ邦訳されてた。ありがたやありがたや。)

で、全編通して面白い記事なのですが、特に興味深かったのが下記のくだり。ちょっと長いけど引用します。

Martin Fowler's Bliki in Japanese - ThoughtWorksでのRuby - Active Recordのテスティング

Active Recordの問題は、データベースアクセスコードをビジネスロジックと一緒にしてしまっていることだ。これでは、データベースダブルを作ることが難しい。 Mingleチームでは、Railsがデータベースと密接に結びついていることを受け入れ、本物のデータベースに対してすべてのコミットテストを実行している。

まったく逆の視点が、AtlantaチームとJerseyチームから提唱された。 Rubyにはメソッドを実行時に再定義できる強力な機能がある。これを使って、Active Recordのクラスにあるデータベースアクセスメソッドを再定義して、Active Recordクラスをスタブ化するのである。チームはこのために gem の unitrecord を使い始めていた。

3年経つが、我々はまだこの議論に決着がついていない。 Mingleチームは、本物のpostgresデータベースに接続して、8分以内に数千ものテストを実行している(マルチコアを活用してテストを並列処理している)。 AtlantaチームとJerseyチームは、コミットテストがスタブなしで8分以内に終わるよりも、スタブありで2分以内に終わることのほうが大切だと考えている。このトレードオフは、データベースを直接テストするシンプルさと、スタブテストの素早いコミットビルドとの対決だと言える。

まあウチの場合は、Rails ではないので、Active Record の問題とまったく同じというわけではありませんが、ビジネスロジックがストアドプロシージャに内包されているので、テストコードから見たら似ていると思います。

で、「マーチン・ファウラーをはじめとする、Thought Works の凄腕たちでも結論が出てないんだ」、ということにちょっと安心したような、やっぱ解答ほしいなぁ、という思いやら、複雑な気持ちです。

ちなみに、ウチは DB にテストデータを流し込んで、実際のデータでテストしてます。(Mingleチーム式)。テスト数は 2万5千くらいだっけ? 8分はかからないけど、多分 3, 4分はかかってますね。(ちゃんと測ってない...)


別件。以前、
データベースのテストってみんなどうやってるんだろ?

Apache のプロセスは Apache::Test を使えばユーザ毎とかに分けるとかできそうだけど、DB はそういうモジュールないし。

と書きましたが、MySQL::Sandbox使えば出来そうな感じです。

MySQL::Sandbox はあくまでもサンドボックスを作るだけっぽい感じなので、マスタデータに関しては何かしら考えないとダメそうですけどね。いずれにせよ、「DB のマスタが正」っていう状態はあんまり健全じゃないから、その辺も踏まえてちゃんと考えればいいのかなぁ。

もうちょっと頑張れば自分なりの答えは出そうな感じですね。


see also:

  1. MySQL::Sandbox - Yet Another Hackadelic
  2. MySQL::Sandbox (2) - Yet Another Hackadelic