はじめに
前回の記事でカバレッジの測定方法を紹介しました。
今回は「C0・C1・C2って何が違うの?」という疑問をわかりやすく整理します。
1. C0・C1・C2の概要
カバレッジには「何を網羅したとみなすか」によって種類があります。
| 種類 | 別名 | 網羅の対象 | 一言で言うと |
|---|---|---|---|
| C0 | 命令網羅(Statement Coverage) | 全ての**行(命令)**が実行されたか | 「全行通ったか」 |
| C1 | 分岐網羅(Branch Coverage) | 全ての分岐の真偽が実行されたか | 「ifのTrueもFalseも通ったか」 |
| C2 | 条件網羅(Condition Coverage) | 全ての条件式の組み合わせが実行されたか | 「条件の全パターン通ったか」 |
2. 図で理解するC0・C1・C2の違い
次のコードで考えます。
def check(a, b):
if a > 0 and b > 0: # ← ここが条件分岐
return "両方正"
return "どちらか0以下"
C0(行カバレッジ)の考え方
テストケース: a=1, b=1 → "両方正" を通る
実行された行: 1行目(if)、2行目(return "両方正") ← 3行目は通っていない
C0達成: NO(3行目が未通過)
テストケース追加: a=-1, b=1 → "どちらか0以下" を通る
C0達成: YES(全行通過)
C1(分岐カバレッジ)の考え方
if文には「Trueのとき」と「Falseのとき」の2分岐がある
テストケース: a=1, b=1 → if が True → "両方正"
テストケース: a=-1, b=1 → if が False → "どちらか0以下"
C1達成: YES(True・Falseどちらの分岐も通過)
C0は通過したがC1は未達、という状況が起こります。
def check(a, b):
result = "OK"
if a < 0:
result = "NG" # C0はここを通過すれば満たせる
return result # C1はif=True・if=Falseの両方が必要
C2(条件網羅)の考え方
and や or で複数条件が結合されている場合、C1だけでは不十分なケースがあります。
if a > 0 and b > 0:
| テストケース | a > 0 | b > 0 | 結果 |
|---|---|---|---|
| a=1, b=1 | True | True | True |
| a=-1, b=1 | False | True | False |
| a=1, b=-1 | True | False | False |
| a=-1, b=-1 | False | False | False |
C2はこの4パターン全てを網羅することを求めます。b > 0 が単独でFalseになるケース(3行目)は、C1だけでは見逃す可能性があります。
3. 使い分けの目安
| レベル | 目安の場面 |
|---|---|
| C0(行カバレッジ) | まず最初に目指すベースライン。「全行は通った」の確認 |
| C1(分岐カバレッジ) | 業務システムやライブラリの標準的な品質目標。pytestの--branchオプションで計測可能 |
| C2(条件網羅) | 金融・医療・安全系など高い信頼性が求められる場面。テスト数が爆発しやすい |
実務では C1を基本目標 とするプロジェクトが多いです。C2は複雑な条件式が多いコードでは組み合わせ数が膨大になるため、重要な箇所に絞って適用するのが現実的です。
4. pytestでC1(分岐カバレッジ)を測定する
pytest --cov=src --cov-branch --cov-report=term-missing
--cov-branch を追加するだけでC1(分岐カバレッジ)も合わせて測定されます。
Name Stmts Miss Branch BrPart Cover Missing
------------------------------------------------------
calc.py 6 0 4 1 88% 5->exit
| 列 | 意味 |
|---|---|
| Branch | 全分岐数 |
| BrPart | 片側しか通っていない分岐数 |
| 5->exit | 5行目からexitへの分岐が未通過 |
HTMLレポートでも黄色で部分的にしか通っていない分岐が表示されます。
pytest --cov=src --cov-branch --cov-report=html
まとめ
| 種類 | 網羅対象 | 使い分け |
|---|---|---|
| C0 | 全行が実行されたか | 最初のベースライン確認 |
| C1 | ifのTrue/False両方を通ったか | 業務システムの標準目標 |
| C2 | 条件式の全組み合わせを通ったか | 高信頼性が必要な箇所に限定 |
pytestで測定するには --cov-branch を追加するだけでC1まで確認できます。
さいごに
「カバレッジ100%=バグゼロ」ではありません。
C0・C1・C2は、あくまで「どれだけ通ったか」の指標です。テストの中身(assertの質)と組み合わせて初めて意味を持ちます。