ソフトウェアテストのカバレッジ基準を順を追って理解する:Line Coverageから MC/DCまで
ソフトウェア開発におけるテスト手法は似たような名前で非常に混乱します。これらの違いを理解することは、テスト実装時の混乱を避けられる、非テスト担当者への説明をスムーズに行えるなどメリットがあると思います。
今回は、ソフトウェアテストでベーシックな5つのカバレッジ基準について、基本的なものから高度なものへと段階的に確認していきます。これらのカバレッジ基準は、それぞれ前の手法の問題点を補完する形で発展してきました。
- Line Coverage だけでは未実行のコードは分かるが、条件分岐のテストが不十分
- Branch Coverage では条件のtrue/falseをテストするが、個々の条件の影響は考慮しない
- Condition Coverage で各条件のtrue/falseをチェックするが、短絡評価の影響でカバーが不十分になる可能性がある
- Multiple Condition Coverage はすべての組み合わせを試すが、テストケースが爆発的に増加する
- MC/DC は「最小限のテストケースで条件の独立性を確認できる」ため、テストケースを抑えつつで高品質のテスト結果を得られる
このように、各カバレッジ基準は、それ以前の手法の欠点を補う形で設計されています。
Line (Statement) Coverage
これは単純明快です。テストコードで全体コードの内、どの程度実行されたかを測るだけ。 テストで実行されたコードの行数/コード全体の行数
です。これって意味があるのかなと思ったのですが、コード内の未実行部分を発見するために開発初期のテストカバレッジ測定では使われるようです。特に人間にとってはソースコードビューとともに実行/未実行がテストツールによって赤/緑で色分けされていれば分かりやすい。とはいえ、ソフトウェアの品質確認としては非常に心もとないため、ブランチカバレッジを併用することになります。
Branch (Decision) Coverage
これは条件分岐に対して最低1回はTrue/Falseになる組み合わせを実行しているかでカバー率を測定します。ポイントは結果重視であること。
例えば、if (A && B)
とあった場合、すべての組み合わせは下記の4パターンですが、ブランチカバレッジではNo.1と[No.2,No.3,No.4のいずれか1つ]の2パターンでTrue/Falseが網羅できますので、テストケースは2つとなります。
No | A | B | Result |
---|---|---|---|
1 | True | True | True |
2 | True | False | False |
3 | False | True | False |
4 | False | False | False |
また条件分岐が複数ある場合は、各条件の影響を独立して
確認する必要があります。次のような疑似コードがある場合を考えてみます。
if A==True {
doSomething1();
}
if B==True {
doSomething2();
}
if C==True {
doSomething3();
}
このコードには3つの独立した分岐があります。ブランチカバレッジを満たすには、各条件分岐がTrue/Falseの両方のパスを通ることが必要です。一見、「TTT」と「FFF」の2パターンで十分と思われるかもしれませんが、これでは「各条件が独立して影響を与えているか」を確認できません。この「独立性」の考え方がないと、無駄なテストが増えたり、カバレッジの抜け漏れが発生します。
例えば「TTT」と「FFF」だけのテストでは、「Aだけを変更した場合の影響」や「Bだけを変更した場合の影響」を独立して検証できていません。ブランチカバレッジの本質は「各分岐の独立した振る舞い」を確認することにあります。
そのため、以下の4つのテストケースが必要となります:
Case | A | B | C | 各 if の通り方 |
---|---|---|---|---|
1 | T | T | T | すべての if に入る |
2 | F | T | T | if(A) を通らない |
3 | T | F | T | if(B) を通らない |
4 | T | T | F | if(C) を通らない |
Condition Coverage
ブランチカバレッジがif
やelse
といった条件文を最低1回は実行するかに注目しているのに対して、コンディションカバレッジは条件文の各部分の変更がTrue/Falseに影響をあたえるかについて注目します。各条件がTrue/Falseのいずれかを1回以上実行しているか確認します。
ブランチカバレッジでの例を再掲します。if(A && B)
とあった場合、すべての組み合わせは下記の4パターンですが、コンディションカバレッジでは[No.1,No.4],[No.2,No.3]のどちらかのペアであれば、A/BそれぞれTrue/Falseという条件が網羅できますので、テストケースは2つとなります。
No | A | B | Result |
---|---|---|---|
1 | True | True | True |
2 | True | False | False |
3 | False | True | False |
4 | False | False | False |
ここで重要な問題点として、短絡評価 (Short-Circuit Evaluation) の影響があります。例えば if(A && B)
の条件では、A = No の場合、プログラム実行時には B は評価されません。これはなぜ問題かというと:
- B の評価が実際には行われない状況でテストしていることになり、実際の実行パスを正確に反映していない
- B の評価に副作用がある場合(例:関数呼び出しや変数の変更)、それが実行されないことによる振る舞いの違いを見逃す可能性がある
- Bに関するバグが隠れたままになる可能性がある
また、条件変化による結果(ブランチ)については考慮しないため、条件のテストだけではブランチカバレッジを満たさない状況もありえます。そのため、より高度なカバレッジ基準が必要とされることになります。
Multiple Condition Coverage
コンディションカバレッジを満たすだけでは、抜け漏れが発生する可能性が存在します。この問題を回避するため、すべての条件文のパターンを総当たりで確認するテストケースがマルチ・プルコンディション・カバレッジです。これはコンディションカバレッジより厳格な基準であり、抜け漏れは発生しませんが、当然デメリットもあります。
- テストケース数が爆発的に増加
- N 個の条件なら 2^N の組み合わせが必要
- 条件が増えるほど、テストケース数が爆発的に増え、非現実的になる
- 冗長なテストが増える
- 結果が同じ不要なケースも含まれる
- 本質的に意味のない(同じ結果になる)テストが多くなる!
- 短絡評価を考慮しないと無駄が多い
- if (A || B)の場合、A=TrueならBは評価されない
- 実際に評価されない条件までテストしてしまう
実践的には「最小限のテストケースで条件の影響を確認する」ことが重要であり、コンディションカバレッジで十分なことが多いのですが、航空/医療などの高信頼性が求められる場面では MC/DC という手法が取られています。
MC/DC (Modified Condition/Decision Coverage)
MC/DCは、各条件が独立して結果に影響を与えることを確認することで、最小限のテストケースで結果に影響する条件変更を網羅します。
MC/DC を満たすためには、以下の4つの条件を満たす必要があります。
- 各条件が少なくとも一度は true と false の両方をとる。
- resultが少なくとも一度は true と false をとる。
- 各条件が独立して、条件式全体の結果に影響を与えることを示すテストが存在する。
- 最小限のテストケースでこれを達成する。
これだけだと分かりづらいので具体的な例を挙げてみます。アップルジュースを提供しようとしたとき、コップ、ジュース、氷という条件があります。この中で、アップルジュース提供に絶対的に必要なものはコップとジュースです。そしてすべての組み合わせは下記表の通りになります。
Case | cup | juice | ice | result |
---|---|---|---|---|
1 | T | T | T | OK |
2 | T | T | F | OK |
3 | T | F | F | NG |
4 | F | T | T | NG |
5 | F | F | T | NG |
6 | F | T | F | NG |
7 | T | F | T | NG |
8 | F | F | F | NG |
MC/DCでは独立して結果に影響に与える条件のみ調査します。従ってiceについてはTrue/Falseどちらだろうとも結果に影響はしません。そのため、調査対象から除外します。コップ/ジュースの要素がそれぞれTrue/Falseになった場合にresultが正しく変化するかを調査します。
- resultがtrue(OK)になる例はCase.1(T,T,T)を選択
- cupだけが0となるCase.4(F,T,T)を選択
- juiceだけが0になるCase.7(T,F,T)を選択
Case | cup | juice | ice | result |
---|---|---|---|---|
1 | T | T | T | OK |
4 | F | T | T | NG(cupの影響) |
7 | T | F | T | NG(juiceの影響) |
これでMC/DCの条件を満たすテストケースが選択されました。MC/DC は「各条件が結果に影響を与えるか」を保証するため、短絡評価を考慮した最適なテストケースを選ぶことが可能となります。
それぞれの長短を押さえましょう
ソフトウェアテストについて知見がない場合、似たような名前のテストが多く、定義の説明も素人には違いが分かりづらく感じるかと思います。また多くの説明で条件変更が独立して結果に影響を及ぼす
ことを暗黙の前提にしていることもあり、より理解を妨げる一要因になっているかと思います。
実際のテストケース作成においては、時間的/金銭的コストとリスク許容度のバランスを個々のケースで考える必要がありますので、ある程度各カバレッジの目指すゴールを把握しておくことは多くの関係者にとって有益であると思います。
Discussion