テストカバレッジ C0/C1/C2/MCC の解説
C0(命令カバレッジ)
-
C0は、プログラム内のすべての**命令(行)**が少なくとも一度は実行されたかどうかを測定します。
-
例:
checkEvenOdd(2)
を実行すると、"Even" が表示され、if
文の中の命令が実行されます。しかし、else
の部分は実行されていません。このため、C0カバレッジは部分的にしか満たされません。checkEvenOdd(3)
を実行すると、else
の部分が実行され、C0カバレッジが100%になります。if (num % 2 !== 0) return;
C1(分岐カバレッジ)
-
C1は、プログラム内のすべての**分岐(if, else if, else)**のパスが通過されたかを測定します。
-
例:
function checkSign(num) { if (num > 0) { console.log("Positive"); } else if (num < 0) { console.log("Negative"); } else { console.log("Zero"); } }
このコードには3つの分岐があります。
-
checkSign(5)
→if (num > 0)
が True で "Positive" と表示。 -
checkSign(-5)
→else if (num < 0)
が True で "Negative" と表示。 -
checkSign(0)
→else
が True で "Zero" と表示。
これら3つのテストケースをすべて実行することで、C1カバレッジは100%になります。すべての分岐のTrue/Falseがテストされる必要があります。
-
C0・C1の違い(カバレッジ100%にするには)
C1(分岐カバレッジ)は、すべての条件分岐がテストされたかどうかを確認します。これには、各条件がTrueまたはFalseの両方の場合がテストされる必要があります。
C1カバレッジを100%にするには?
- この関数には、2つの分岐があり、それぞれの結果(True/False)を確認する必要があります。
-
if (num > 0)
-
True の場合 →
checkSign(5)
を実行すると、「Positive」が表示されます。 -
False の場合 →
checkSign(0)
またはcheckSign(-5)
を実行すると、次の分岐に進みます。
-
True の場合 →
-
else if (num < 0)
-
True の場合 →
checkSign(-5)
を実行すると、「Negative」が表示されます。 -
False の場合 →
checkSign(0)
を実行すると、最後のelse
に進みます。
-
True の場合 →
結論
-
checkSign(5)
は、if (num > 0)
が True の場合をカバーします。 -
checkSign(-5)
は、else if (num < 0)
が True の場合をカバーします。 -
ただし、C1カバレッジを100%にするためには、
checkSign(0)
を実行して、else
に到達する必要があります。
checkSign(0)
を実行しない場合、else
の分岐がカバーされないため、C1カバレッジは100%にはなりません。すべての分岐(True/Falseの道)が通らないと、C1カバレッジは100%とみなされないのです。
したがって、checkSign(0)
を実行して初めて、全ての条件のパス(True/False)を通ったことになり、C1カバレッジが100%になります。
C2(条件カバレッジ)
-
C2は、すべての条件の組み合わせがテストされたかどうかを確認します。複数の条件がある場合、それぞれの条件がTrue/Falseになるケースを全てテストする必要があります。
-
例:
function checkEligibility(age, hasLicense) { if (age >= 18 && hasLicense) { console.log("Eligible to drive"); } else { console.log("Not eligible to drive"); } }
この場合、
age >= 18
とhasLicense
の2つの条件があります。
テストケース:-
checkEligibility(20, true)
→ True, True -
checkEligibility(16, true)
→ False, True -
checkEligibility(20, false)
→ True, False -
checkEligibility(16, false)
→ False, False
これら4つのケースですべての条件の組み合わせをテストし、C2カバレッジが100%になります。
-
MCC(循環的複雑度)
-
MCC(循環的複雑度)は、コード内の独立した実行パスの数を測定します。これはコードの複雑さを数値化するもので、分岐が多いほど値が高くなります。
-
計算式:MCC=E−N+2PMCC=6−8+2=0
MCC=E−N+2PMCC = E - N + 2P
- E: 分岐(エッジ)の数
- N: ノード(命令や条件)の数
- P: プログラムのエントリポイントの数(通常1)
例:
function determineAction(weather, temperature) { if (weather === "sunny") { if (temperature > 25) { console.log("Go to the beach"); } else { console.log("Go for a walk"); } } else if (weather === "rainy") { console.log("Stay indoors"); } else { console.log("Check the forecast"); } }
この場合、MCCを計算するために次のようにノードとエッジを数えます。
- ノード数(N): 8
- エッジ数(E): 6
- エントリポイント(P): 1
計算すると、
MCC=6−8+2=0MCC = 6 - 8 + 2 = 0
よって、このコードの循環的複雑度は 2 です。
MCC(循環的複雑度)とは?
MCC(McCabeの循環的複雑度)は、プログラムのコードがどれだけ複雑か、またはどれだけの異なる実行パス(コードの流れ)が存在するかを数値で表す指標です。MCCの値が高いと、そのコードには多くの異なる実行経路があり、バグのリスクが増え、テストもしっかりしなければならないことを意味します。
MCCを使う理由
プログラムが複雑になるほど、テストすべき分岐やルートが増えていきます。MCCを使ってプログラムの複雑さを数値で把握し、テスト計画やコードの品質改善に役立てることができます。
MCCは、分岐がどれだけあるかに着目します。分岐は、if
文や for
ループ、while
ループ、switch
文などが例です。それぞれの分岐は、プログラムがいくつかの異なるルートを通る可能性を生み出します。
MCCを数える方法
MCCを数えるには、次の式を使います:
MCC=E−N+2P\text{MCC} = E - N + 2P
MCC=E−N+2P
- E(エッジ): プログラムの分岐の数(各条件やループによって新しく生まれるルート)
- N(ノード): プログラムのノードの数(分岐や命令のポイント)
- P(エントリポイント): プログラムの開始点。通常は1。
実際の例で見てみましょう
次のコードを例にします。
function determineAction(weather, temperature) {
if (weather === "sunny") {
if (temperature > 25) {
console.log("Go to the beach");
} else {
console.log("Go for a walk");
}
} else if (weather === "rainy") {
console.log("Stay indoors");
} else {
console.log("Check the forecast");
}
}
1. ノード(N)を数える
ノードは、プログラムの分岐や命令の数を表します。このプログラムには次のノードがあります。
-
if (weather === "sunny")
→ ノード1 -
if (temperature > 25)
→ ノード2 -
console.log("Go to the beach")
→ ノード3 -
console.log("Go for a walk")
→ ノード4 -
else if (weather === "rainy")
→ ノード5 -
console.log("Stay indoors")
→ ノード6 -
else
→ ノード7 -
console.log("Check the forecast")
→ ノード8
ノードの合計 = 8
2. エッジ(E)を数える
エッジは、プログラムの分岐によって生まれる新しいルートです。例えば、if
文や else
でコードの実行が異なる場合、1つの分岐から2つのエッジが生まれます。
-
if (weather === "sunny")
→ True/False → 2つのエッジ -
if (temperature > 25)
→ True/False → 2つのエッジ -
else if (weather === "rainy")
→ True/False → 2つのエッジ
エッジの合計 = 6
3. エントリポイント(P)
エントリポイントは、プログラムの開始点です。通常、1つのプログラムには1つのエントリポイントしかありません。
エントリポイント = 1
MCCを計算する
今、MCCの公式に当てはめて計算します。
MCC=E−N+2PMCC = E - N + 2P
MCC=E−N+2P
- E = 6 (エッジの数)
- N = 8 (ノードの数)
- P = 1 (エントリポイントの数)
これを公式に当てはめると:
MCC=6−8+2(1)=0MCC = 6 - 8 + 2(1) = 0
MCC=6−8+2(1)=0
結果:
MCC=2MCC = 2
MCC=2
MCCの解釈
- MCC = 1 の場合:非常にシンプルなプログラム(分岐なし)。
- MCC = 2 の場合:いくつかの分岐があるが、比較的シンプルなプログラム。
- MCCが高ければ高いほど、プログラムは複雑で、異なる実行パスが多くなります。そのため、テストすべきルートが増え、バグが潜む可能性も増えるということです。
まとめ
- MCCは、コード内の分岐やループなどを考慮して、どれだけの異なる実行パスがあるかを示す指標です。
- 値が大きいほど、コードは複雑であり、多くのパスがテストされる必要があります。
- MCCを理解することで、コードのテストがどれだけ必要か、そしてコードの複雑さがどれだけ高いかを把握できます。
このようにして、MCCを使うと、プログラムがどれだけテストされるべきかや、コードの改善点が見つけやすくなります。
4o
Discussion