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

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

DBのスキーマ変更をテストする

ずいぶん前から実施しているのだけど、書いてなかったので書きます。

皆様は DB のスキーマ変更(ALTER TABLE)ってどうやって管理していますか?SQL 手打ちは論外として、事前に変更の SQL を作るとしても、テストしたいですよね?

と、いうわけで、こんな感じに書ける物体を使っています。

use Test::MyProj::Schema;
use Test::More;

my $schema = Test::MyProj::Schema->new({
    svn_schema_base => 'Rel-1.00',
    patch_dir => '../../ddl/patch/Rel-1.01',
});
$schema->current_schema_ok();
$schema->patched_schema_ok();

テストファイルの名前を、テーブル名にしています。

で、current_schema_ok では、「今のスキーマ(ファイルに書かれた CREATE文)」と「実際のDB のスキーマ(SHOW CREATE TABLEしたやつ)」が一致しているかをテストします。

patched_schema_ok は、ちょっと分かりにくいのですが、svn_schema_base で「基準になるスキーマDDL のバージョン」を書いて、patch_dir に「そのリリースで適用するパッチ(ALTER TABLE)のディレクトリ」を書きます。つまり、「『前のバージョン(CREATE) + パッチ(ALTER TABLE) = 今のバージョン』になるよね!」というテストです。*1。「今のバージョン」は CREATE 文になるようにしています。*2

で、CI サーバでチェックしつつ、ステージング環境にアップした際もテストを実施してます。

本当はもうちょっと汎用的なつくりにして、github なり CPAN なりにアップしたいのですが、プロジェクトのディレクトリ構造に依存しまくるし、僕は仕事では svn しか使ってないので、他の VCS に対応とかやりたくないし、ってか今のプロジェクトでしか使ってないから、実は汎用化するモチベーションもあんまりないかも、みたいな感じです。

*1:この例だと、前のバージョンが Rel-1.00、今(開発中)のバージョンが Rel-1.01 です。

*2:「次のバージョン(1.02)」になった時に、「1.00の CREATE 」+「1.01のパッチ」+「1.02のパッチ」という形で管理するのはめんどくさいなー、と考えているためです。このへんは異論ありそう