SQLのカバレッジ
SQLの条件記述ミスは、テストで発見できず、重大な問題(他の人のデータが覗けるなど)を引き起こすことがままあります。
この原因は、テストのカバレッジが足りていないことにあります。SQLを呼び出す側のカバレッジ計測に関して、いくらC1(判定条件網羅), C2(条件網羅)だといっても、SQLの中の条件文は測れません。
そこで、SQLのカバレッジについて考えてみたいと思います。*1
というSQLに対して、
SELECT count(*)
FROM emp E, dept D
WHERE E.dept_cd=D.dept_cd
AND E.salary > 300000
AND D.delete_flg = '0'
従業員 | ||
emp_cd | dept_cd | salary |
001 | 01 | 01500000 |
部門 | |
dept_cd | delete_flg |
01 | 0 |
しかし、例えば次のようにSQLの条件が抜けていても、期待する結果=1、実行結果=1で、テストはパスしてしまいバグは検出できません。
SELECT count(*)
FROM emp E, dept D
WHERE E.dept_cd=D.dept_cd
AND E.salary > 300000
これが、部門が削除されたときに初めて発覚するバグを生み出すことになります。
SQLの場合、カバレッジをどう考えればよいかは、SQLを馴染みのコードに変換してみれば分かりやすいです。
これをテストする場合を考えるのです。
if ( $emp->dept_cd eq $dept->dept_cd
&& $emp->salaly > 300000
&& $dept->delete_flg eq '0')
{
return true;
}
つまり、WHERE句がIF文に相当し、これに対するテストケースがデータになります。
従業員 | ||
emp_cd | dept_cd | salary |
001 | 01 | 01500000 |
002 | 02 | 01200000 |
部門 | |
dept_cd | delete_flg |
01 | 0 |
02 | 1 |
03 | 0 |
04 | 1 |
このように用意されていれば、すべてのC2(条件網羅)のカバレッジが確保できテスト量としては合格ラインだといえます。
組合せが爆発しそうに見えますが、SQL単体でカバレッジを測れば、
ということになり、複雑なSQLでも10前後の条件数でしょうから、用意すべきデータは、1000件程度でよいことになります。テーブルの結合があると、実質用意すべきデータ数はもっと少なくなります。
WHERE句のAND, ORの条件数をnとすると、用意すべきデータの総件数mは、
m = 2 ^n
*1:ちょうどhttp://d.hatena.ne.jp/nowokay/20050823#1124744144で同様のことが語られていました...なるほど...