ここではSQLSERVER,ORACLEといったサーバーを構築するタイプのデータベースを使用した開発やテスト環境の作成・管理と自動テストについての考察を行う。
SQLITEやACCESSといったファイルベースのものは対象外とする。
#作業者に与える環境について
作業者にあたえるデータベースの環境をどうするべきか?
最善の方針は1作業者が1つのデータベースのインスタンスを扱えるようにすることである。
インスタンスが困難なら、スキーマーで分離するのも手である。
もっとも不味いのは、1つの環境で複数の作業者が、開発やテストを行うことになることだ。
これは、開発者がおこなったテストが別の開発者に影響をあたえる可能性があるからだ。
このことは余計なリスクを作成する。
##作業者のローカルPCにデータベースをいれるかどうか?
作業者のローカルPCにデータベースをインストールすべきかどうかは議論が出る。
作業のしやすさでいったら、ローカルPCに置いた方が良い。
これには少人数で管理が行き届く場合に限る。
なぜならば、管理が行き届かない場合、必ず古い環境で開発を続行し続けるという人間がでる。
これは余計なリスクを作ることになる。
作業者の力量が信用できるなら、ローカルで構築させたほうが間違いなく大きな成果がでるだろう。
しかし、力量が足りないなら、1つのデータベースのサーバで、管理者が、すべての作業者の環境を用意してやるほうがよい。
##環境の同期
作業者毎に環境を用意した場合、問題になるのはDatabaseの同期である。
ストアドプロシージャーやファンクションの管理については、スクリプトをテキストとして管理したほうがよい。
これを通常の構成管理(SubversionやGit)で管理する。そこからダウンロードしてきて、データベースに適用すればよい。
それ用のバッチファイルなりシェルスクリプトを記述して配布する。
適用するタイミングはどうするか?
開発者に対してのデータベースなら、自分でやらせればいいだろう。
これは他のソースコードの同期と同じだ。
テスト用のデータベースは少し考えたほうがよい。
テスト中はどのバージョンでテストしているかを明確にするため、更新は避けるべきだ。
テストの区切りがついたタイミングで同期を行うといいだろう。
あと確実に問題になるのは、データベースに最新のプロシージャがあたっているかどうかのチェックが問題になると思われる。
ストアドプロシージャはデータベースの特定のテーブルに格納されているので、それを抜き出してきて比較してやればよい。
SQLSERVERの時は以下のGetSpMd5.wsfで各ストアドをmd5の値にして、それを比較してチェックをおこなえる。
https://github.com/mima3/SqlServerScript
テーブルの構成などが変わった場合の更新は難しい。
テストデータを初期化していいなら、スクリプトを流すだけでいいだろう。
しかし、テストデータを保持したい場合は、状況に合わせた臨機応変な対応を求められる。
場合によっては更新用のスクリプトを書く必要もある。
#データベースに関係するテストの自動化
データベースを使った自動テストについて考察する。自動テストは3段階にわかれる。
1 テスト環境の準備
2.テストの実行
3.結果の検証。
1はテーブルの作成、ストアドの作成、初期データの作成などを行う。
この工程はスクリプトを記述しておいたほうがよい。
既存にデータベースが存在する場合でも、これらのスクリプトは現在の状態から作成できる機能があるはずだ。
(仮になくても、これらの情報はすべてシステムテーブルに書き込まれているので、自分でつくれるはず)
2 テストの実行は、まずテストデータを作成した後に、テスト対象の処理を実行する。
テストデータをCSVでもつか、SQL文のスクリプトで管理するか議論があるだろう。
可能なら、CSVでもって、テスト時になんらかの処理でSQLに変換したほうがよい。
CSVならExcelを使用してテストデータを作成できるので、楽である。
ここまではすべてスクリプトに記述できる処理である。
テスト対象の処理の実行が自動化できるかどうかは、その処理次第だろう。
ただ、仮にGUIであったとしてもUWSCなどでやろうと思えばやれる。この辺りは費用対効果で考えた方が良い。
3 テスト結果の検証。
基本的にはテスト対象の処理を実行した後に、テーブルの内容がどのように変わるか、あるいはテスト対象が出力したファイルなりが、期待通りであるかをチェックする。
テーブルの内容がどう変わったかチェックするのは、スクリプトで出来るだろう。期待値を外部ファイルなりに保持しておき、それと現在の内容をつき合わせて確認する。
期待値もテストデータと同様CSVでもてば、Excelで編集できる。
一つ注意しないといけないのは、実行のたびに変わるデータの扱いだ。たとえば、更新日や更新者などは実行のたびに変わるだろう。
これは比較の対象から外しておいた方がいいだろう。
もし、更新日時の確認をどうしてもしたい場合、単純なdiffでなく、更新日時がテスト実行開始〜終了の間に収まっているかどうかチェックする。
あるいは期待値用のデータに特定の文字列を入力しておけばいい。たとえば、「@USER」ならば現在ユーザに変換してからチェックする。
このように、実行のたびに変わるデータの扱いは多少工夫が必要だろう。
更新ロックがかかっているかどうかの試験も、自動でやろうと思えばできる。
これは、別プロセスでロック用のスクリプトを実行して指定のテーブルに更新ロックを掛けてコミット、ロールバックせずに待機する。
その間にテスト対象の処理を実行して例外がかえってくることを確認する。
テストがおわったらロック用のスクリプトを終了してやって、再度、テスト対象を実行して今度は正常に動作することを確認すればよい。
テスト用のスクリプトを書く際にはどの環境でも、動くようにを記述することが重要だ。
まちがっても、絶対パスでファイルの場所などを書いてはいけない。
また、ユーザ名などはテスト共通のユーザを使ったほうが楽だろう。
##懸案事項
DBのテストの最大の問題は時間がかかることだ。
コミット時の自動テストには不適切な速度になる可能性が高い。
なので、テストには必ずやる重要項目と、それ以外にわけておき、オプションですべてテストするかどうかを指定できるようにしたほうがのぞましい。
また、本番環境で実行されないようにする工夫が必要だ。
本番環境とテスト環境のログインユーザーなどが同じにしておくと、本番データを吹き飛ばす可能性があって危険だ。テストデータをスクリプトで管理していると、それをまちがって本番に流しかねないリスクがある。
可能なら、テストデータのスクリプトの先頭に想定以外のDBではテストを中断するなどのロジックが必要かもしれない。