SQLのカバレッジ

SQLの条件記述ミスは、テストで発見できず、重大な問題(他の人のデータが覗けるなど)を引き起こすことがままあります。
この原因は、テストのカバレッジが足りていないことにあります。SQLを呼び出す側のカバレッジ計測に関して、いくらC1(判定条件網羅), C2(条件網羅)だといっても、SQLの中の条件文は測れません。


そこで、SQLカバレッジについて考えてみたいと思います。*1


SELECT count(*)
FROM emp E, dept D
WHERE E.dept_cd=D.dept_cd
AND E.salary > 300000
AND D.delete_flg = '0'
というSQLに対して、

01
従業員
emp_cddept_cdsalary
00101500000


部門
dept_cddelete_flg
010
というデータだと、期待する結果=1、実行結果=1となり、テストをパスします。
しかし、例えば次のように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文に相当し、これに対するテストケースがデータになります。


0101
従業員
emp_cddept_cdsalary
00101500000
00202200000


部門
dept_cddelete_flg
010
021
030
041

このように用意されていれば、すべてのC2(条件網羅)のカバレッジが確保できテスト量としては合格ラインだといえます。
組合せが爆発しそうに見えますが、SQL単体でカバレッジを測れば、


WHERE句のAND, ORの条件数をnとすると、用意すべきデータの総件数mは、
m = 2 ^n
ということになり、複雑なSQLでも10前後の条件数でしょうから、用意すべきデータは、1000件程度でよいことになります。テーブルの結合があると、実質用意すべきデータ数はもっと少なくなります。

*1:ちょうどhttp://d.hatena.ne.jp/nowokay/20050823#1124744144で同様のことが語られていました...なるほど...