テストデータのセットアップ
Seasarのからさわぎ@大阪行ってきました.設計手法「くーす」の話.以下感想.
- 一番最初にUIモック(画面プロトタイプ)を作れってのはいい.オブジェクト指向だと具体的な画面UIをなるべく排除するのがいいとされているが,そうするとユーザはついてこれない.
- ロバストネス分析使えそう.でも用語はイヤ(バウンダリ,コントロール)
- シナリオ分析かなりだるそう.やってられない.
- 業務ロジックがStatelessということは,シナリオベースではなくメソッドベースのテストケースを書いてる?
- 完璧なインターフェイス仕様を求めてるところはウォーターフォールっぽい?
以下,あんまり関係のないこととか
- くーすって沖縄のお酒の名前?
- きむきむさん=オレジュさん?
- はぶさんのホワイトボードによるフォローうまい.ひがさんといいコンビですな.
- 景品(Perl/CGI本)欲しいと思ったの僕ぐらい? 場違いPerlプログラマって僕だけ?(泣).
まあそんな感じ.くーすは機会があればぜひ使ってみようと思ったんですが,ただ受け入れられないことが....
自分Excelなんか嫌いですから!!! 残念!!!
ひがさんのVBA使ってくださいっていう言葉に頭くらくらしました(T_T).
というわけで,自分がくーす使うとしたらこんなふうにカスタマイズ.
- Excelで書く部分はXML(+RubyでHTMLに出力)に変更
- シナリオ分析はRubyスクリプトに変更
(シーケンス図:RubyUnitテストケース,インターフェイス仕様:Rubyのクラス定義)
あるいはシナリオ分析はしょっていきなりJUnit+POJOでテストコード書き始めるかもしれないな.
さて,からさわぎでは説明がなかったが,SeasarではテストデータをExcelに準備してテストコードが書けるらしい.
僕の場合は,もちろんExcelは使わないし,別ファイルに書いたりもしない.テストデータは直接テストコードに書き込む派だ.ただ,テストデータをうまく埋め込まないと冗長でわかりにくいテストコードなってしまう.そこで,どんなふうにテストデータをセットアップしているか紹介しよう(但しPerlUnit).
まずDBテストを行うためのテストケースを定義する(SampleDBTestクラス):
package SampleDBTest; use base qw(Test::Unit::TestCase); use Test::Unit::Sql; sub set_up { my $self = shift; $self->sql_set_up; } sub tear_down { my $self = shift; $self->sql_tear_down; } ...
このクラスはTest::Unit::TestCaseの子クラスだが,Test::Unit::Sqlを宣言している(Test::Unit::Sqlは自作&非公開).このように書かれたテストケースはDBテスト用メソッドが使えるようになる(但し上のようにset_up, tear_downで個別にsql_set_upとsql_teardownメソッドを呼ぶ必要あり).
まず一番よく使うのがsave_tableメソッド:
my $employee = $self->save_table('employee');
save_tableメソッドはその名の通り,employeeテーブルを保護するメソッドだ.テスト側でemployeeテーブルをどういじってもマスターのテーブルには影響しない(DBのテスト参照).
また,このメソッドはTableオブジェクトを返す.Tableオブジェクトのinsertメソッドでレコードを追加していくことができる:
$employee->insert(emp_no => 1, dept_cd => '10', name => '従業員1'); $employee->insert(emp_no => 2, dept_cd => '10', name => '従業員2');
これでemployeeレコードを2件追加したことになる.名前つき引数でレコードのフィールド名と値を指定する.もしNULLを設定したいならundefでOKだ:
$employee->insert(emp_cd => 999, dept_cd => undef, name => '幽霊従業員');
このメソッドが使いやすいのは,明示的に指定のないフィールドにはダミー値が設定されることだ.これによってNOT NULL制約がたくさん書かれたテーブルでも簡単にテストデータを用意できる.
さらに,こんなこともできてしまう:
$employee->insert(emp_no => [10, 11, 12]); $employee->insert(emp_no => [(20 .. 29)]); $employee->insert(emp_no => [40, 41], dept_cd =>['40', '41']);
このコードでは,フィールド値に配列を指定している.こうすると配列が展開された件数分だけレコードが追加される.つまり,1行目はemp_noが10, 11, 12の3レコードを追加,2行目は20〜29までの10レコードを追加,3行目は各配列の直積,つまり(emp_no, dept_cd) = (40, '40'), (40, '41'), (41, '40'), (41, '41')の4レコードを追加する.集計データのテストを書くときに便利だ.
他に名前つき引数のいいところは,デフォルトパラメータを別に用意できることだ.具体的には次のようになる:
my %default_params = (emp_type => 1, update_time => '2004/09/12'); $employee->insert(emp_no => 100, %default_params); $employee->insert(emp_no => 200, %default_params); $employee->insert(emp_no => 300, %default_params, emp_type => 2);
こうするとemp_typeが1,update_timeが2004/09/12のデータをデフォルトで設定できる.但し,最後のemp_no:300のレコードはemp_type:2で上書きしている(後書き優先).Perlではこんなことも可能だ.これでテストデータはかなり簡略化できる.
以上で,save_tableメソッドの説明は終わりだが,この他にsave_load_tableメソッドがある.このメソッドは,CSVデータをレコードにインサートするメソッドだ:
$self->save_load_data( company => " 01,会社1 02,会社2 03,会社3 " dept => " 01,1a,部署1a 01,1b,部署1b 02,2a,部署2a 03,3a,部署3a " );
のコードでは,companyテーブルに3件のレコード,deptテーブルに4件のレコードをCSV形式でインサートする(Perlでは文字列中に改行しても大丈夫).上のコードは次と同じだ:
$self->save_data('company'); $self->save_data('dept'); $self->load_data( company => " 01,会社1 02,会社2 03,会社3 " dept => " 01,1a,部署1a 01,1b,部署1b 02,2a,部署2a 03,3a,部署3a " );
テーブルのカラム数が少ないマスタデータなどはsave_load_dataを利用すればよい.load_table, save_load_tableメソッドの問題点は,CSVにすべてのフィールド値を列挙しないといけないことだ.スキーマの仕様変更に弱いため注意する必要がある.
最後に,execute_sqlというメソッドがある.これはSQL文をそのまま発行するメソッドだ.
$self->execute_sql(" update employee set name = '新従業員名1' where emp_no = 1; update employee set name = '新従業員名2' where emp_no = 2; ");
これまでのメソッドでカバーしきれない部分はこのメソッドを利用すればよい.
テストデータのセットアップコードを書くポイントは,特殊解をあらわにするメソッドを用意するということだ.これはJUnit実践講座にも書いた.テストに無関係な部分は極力テストコード上に出ないようにし,関係のあるデータだけ浮き上がってくるように心がける.そうすればわかりやすいテストコードが書けるようになるだろう.
| 固定リンク | コメント (4) | トラックバック (0)