【コード解説付き】C0 / C1 / C2カバレッジとは?初心者でも分かるソフトウェアテストの基礎

ソフトウェアテストをしていると必ず出てくる疑問があります。
どこまでテストをすれば十分なのか?
その指標のひとつが コードカバレッジ(Coverage) です。
この記事では、テスト現場で特に重要な 3 つの指標
C0(命令網羅) / C1(分岐網羅) / C2(条件網羅) / MCC(複合条件網羅)
を、実例を交えてわかりやすく解説します。
じゃんけん判定コードを例にカバレッジを理解する
ここでは、サンプルコードを使って「どの部分がどのカバレッジに関係するのか」を理解していきます。コードの流れを把握しておくと、C0〜C2 の違いが一気に分かりやすくなります。
function janken($player1, $player2) {
$validHands = ['rock', 'paper', 'scissors'];
if (!in_array($player1, $validHands) || !in_array($player2, $validHands)) {
return 'invalid';
}
if ($player1 === $player2) {
return 'draw';
}
if (
($player1 === 'rock' && $player2 === 'scissors') ||
($player1 === 'scissors' && $player2 === 'paper') ||
($player1 === 'paper' && $player2 === 'rock')
) {
return 'player1_wins';
}
return 'player2_wins';
}
コードの判定パターン(4種類)
invalid: 不正入力(手が rock/paper/scissors でない)draw: 引き分け(手が同じ)player1_wins: プレイヤー1の勝ちplayer2_wins: プレイヤー2の勝ち
この 4 種類の結果が、カバレッジ設計の中心になります。
C0(命令網羅)とは?
C0 カバレッジは、最も基本的でシンプルなカバレッジ指標です。
まずはここを理解することで「カバレッジの考え方」に慣れることができます。
C0 の定義
C0 は コード内のすべての命令(実行文)を少なくとも 1 回通す という基準です。
ポイントは if の中に入らなくても“条件式が評価されれば通ったことになる” という点です。
C0 は 1 ケースでも達成できる例
例えば以下のケース:
janken('rock', 'scissors');これはすべての if 文の条件式が評価されるため、C0 を満たします。
- invalid チェック:false → 次へ
- draw チェック:false → 次へ
- player1 勝利条件:true → return
各行の「評価」は発生しているため、C0 を満たしています。
C0 でよくある勘違い:評価されていない命令はカウントされない
C0 では「途中で関数が終了してしまうと後続の命令が評価されない」という落とし穴があります。
❌ invalid × invalid の場合
janken('invalid', 'invalid');最初の if で return されるため、
- draw チェック
- player1 勝利チェック
- 最後の return
これらが一度も評価されません。
→ C0 不達成
❌ draw(あいこ)だけの場合も同じ
janken('rock', 'rock');これも「途中で終了」するため、後続の命令が評価されません。
C0 の本質(ここが超重要)
C0 = すべての条件式を“一度でも評価させる”こと。
評価されていない if が 1 つでもあると C0 不達成。
C0 は簡単に達成できそうに見えて、実は「early return(途中 return)」によって未評価の命令が残りやすいのが難点です。
C1(分岐網羅)とは?
C1 は、現場で最もよく利用されるカバレッジ基準です。
「この程度は最低やっておきたい」という、多くのプロジェクトの標準ラインです。
C1 の定義
C1は すべての分岐(if 文)で true と false の両方を通す 必要があります。
C0 と違って、「条件式の中に入るかどうか」まで確認する必要があります。
C1 は最小 4 ケースで達成可能
- invalid
- draw
- player1_wins
- player2_wins
これらを最低 1 回ずつ通る必要があります。
例:C1 を満たす 4 ケース
janken('invalid', 'rock');
janken('rock', 'rock');
janken('rock', 'scissors');
janken('rock', 'paper');これにより、全ての if が true も false も通ります。
C1 の弱点:複雑な条件の内部は網羅できない
player1 勝利条件には 3 種類ありますが、C1 では 1 種類通れば OK になります。
- rock → scissors
- scissors → paper
- paper → rock
このように、「内部の条件の組み合わせまではカバーできない」という弱点があります。
C2(条件網羅)とは?
C2 は、もっとも厳密で「テスト漏れを極限まで減らす」カバレッジです。C1 と組み合わせて使うことが推奨されます。
C2 の定義
C2 は すべての条件式について、各条件が少なくとも 1 回 True と 1 回 False になるようにテスト します。
複合条件(OR や AND)を持つ if がある場合、その個々の条件の真偽をテストしますが、すべての組み合わせをテストする必要はありません。
重要: C2 と複合条件網羅(MCC)は異なります。C2 は各条件が True/False になることを確認しますが、すべての組み合わせは不要です。
C2 を満たすテストケース
じゃんけんの例では、C2 を満たすには 最小 6 ケース 必要になります。
例:C1 を満たす 4 ケース
// 【入力チェック】2ケース
janken('invalid', 'rock'); // 第1条件True
janken('rock', 'invalid'); // 第2条件True
// 【引き分けチェック】2ケース
janken('rock', 'rock'); // 条件True
janken('rock', 'scissors'); // 条件False
// 【プレイヤー1勝利チェック】2ケース
janken('rock', 'scissors'); // 条件True
janken('rock', 'paper'); // 条件False
C2 の重要な注意点
C2 だけでは C1 を満たさない場合があります。
例えば、if (A || B) という条件で以下のテストをした場合:
- (A=True, B=False) → 全体は True
- (A=False, B=True) → 全体は True
この場合、A と B は両方 True/False を経験していますが(C2 達成)、if 文全体が False になるケースがテストされていません(C1 未達成)。
実務では「C1/C2 カバレッジ」として両方を満たすことが推奨されます。
MCC(複合条件網羅)とは?
MCC は、最も厳密で「テスト漏れを極限まで減らす」カバレッジです。
MCC の定義
MCC(Multiple Condition Coverage)は 条件式に含まれるすべての条件の組み合わせを網羅 します。
複合条件(OR や AND)を持つ if がある場合、その内部の真偽パターンをすべて確認しなければなりません。
C2 との違い:
- C2:各条件が少なくとも 1 回 True/False(組み合わせは不要)
- MCC:すべての条件の組み合わせをテスト
MCC が重い理由:組み合わせが爆発的に増える
じゃんけんの例では、MCC を満たすには 最低 12 ケース 必要になります。
例:C1 を満たす 4 ケース
// 【入力チェック】3ケース
janken('invalid', 'invalid'); // 両方無効
janken('invalid', 'rock'); // player1無効
janken('rock', 'invalid'); // player2無効
// 【引き分け】3ケース
janken('rock', 'rock'); // グー同士
janken('paper', 'paper'); // パー同士
janken('scissors', 'scissors');// チョキ同士
// 【プレイヤー1勝利】3ケース
janken('rock', 'scissors'); // グー > チョキ
janken('scissors', 'paper'); // チョキ > パー
janken('paper', 'rock'); // パー > グー
// 【プレイヤー2勝利】3ケース
janken('rock', 'paper'); // パー > グー
janken('paper', 'scissors'); // チョキ > パー
janken('scissors', 'rock'); // グー > チョキ複雑なロジックほど、組み合わせが増え、テストコストが重くなるのが MCC の特徴です。
C0 / C1 / C2 / MCC の違いをまとめて理解する
カバレッジ指標は、網羅性とコストのバランスで選ぶ必要があります。
| カバレッジ | 内容 | 必要ケース数 | 特徴 | 実務での用途 |
|---|---|---|---|---|
| C0 | 命令を一度以上評価 | 1 | 最小・簡単 | 動作確認、最低限の品質保証 |
| C1 | true/false を全て通す | 4 | バランス良 | ほぼ標準的な品質確保 |
| C2 | 各条件が少なくとも1回True/False | 6 | 個々の条件に着目 | 複雑な条件式の検証(C1と組み合わせ推奨) |
| MCC | 条件の全組み合わせを通す | 12 | もっとも厳密 | 金額計算、権限ロジック、セキュリティ系 |
実務でのカバレッジ設計のおすすめ
現場では、以下のような基準で使い分けるのが現実的です。
① 基本は C1(80%)を目指す
C1 は実務で最も加重なライン。
無駄なテストを増やさずにメリハリのあるテストができます。
② 複雑な条件式は C2 も組み合わせる
複雑な OR/AND 条件がある場合、C1 だけでは個々の条件の動作が確認できません。
C1/C2 カバレッジとして両方を満たすことで、より高い品質を確保できます。
③ 重要ロジックは MCC を適用
不具合の影響が大きい箇所は MCC を適用する価値があります。
- 売上計算
- 課金ロジック
- ログイン判定
- 権限チェック
など
④ 時間がない場合や低リスク箇所は C0
最低限の動作保証だけで十分な場合は C0 で済ませるという判断も適切です。
④ カバレッジだけでは品質保証できない
カバレッジは「一部の指標」にすぎず、以下も欠かせません。
- 境界値分析
- 異常系テスト
- 性能テスト
- 統合テスト
まとめ
- C0 は「すべての条件式が評価されること」が必須
- C1 は「実務で最もバランスが良い基準」
- C2 は「個々の条件に着目するが、C1 と組み合わせて使うべき」
- MCC は「重要なロジックに適用すると効果大」だがコストも高い
カバレッジは万能ではありませんが、テストの”漏れを可視化”する大事な指標です。
プロジェクトのリスクや予算に応じて、C0〜MCC をうまく使い分けることが品質向上の近道です。
重要:C2 と MCC を混同しないこと
C2 は「各条件が True/False を経験する」、MCC は「すべての組み合わせをテスト」という明確な違いがあります。
資料によっては C2 を MCC の意味で使っている場合もあるため、定義を確認することが重要です。に応じて、C0〜C2 をうまく使い分けることが品質向上の近道です。
