コードカバレッジが一般的にどのように機能するかを知っており、ブランチカバレッジとは何かを知っています。しかし、ブランチカバレッジがループを処理する方法についての説明は見当たらないようです。
パスカバレッジのように機能しますか? 10回実行されるループは、11回実行されるまったく同じループとは異なるパスです。それとも、これら2つのケースはブランチのカバレッジで同じですか?
ブランチカバレッジとパスカバレッジは異なる概念です。
分岐カバレッジを測定するには、分岐が発生する可能性のあるすべてのポイントを探します。各分岐点で、両方の分岐が少なくとも1回実行されている必要があります。例えば。この疑似コードでは:
A
if B:
C
else:
D
E
if F:
G
I
2つの分岐点– if B
およびif F
条件。完全なブランチカバレッジを取得するには、これらの条件のそれぞれがtrueとfalseのブランチを実行する必要があります。つまり、B
とF
の両方がそれぞれfalseとtrueでなければなりません。テスト計画は次のようになります。
Run 1:
B = false
F = false
# executes A B _ D E F _ I
Run 2:
B = true
F = true
# executes A B C _ E F G I
ご覧のように、完全な分岐カバレッジは完全なステートメントカバレッジを意味します。
ループを処理するときは、条件とゴトのみを持つより低レベルの表現に「コンパイル」すると役立つ場合があります。例えば。:
// C99 code
A;
for (int i = 0; i < length; ++i)
B;
C;
として理解できる
// Block 1
A;
int i = 0;
// Block 2
loop_start:
if (!(i < length))
goto loop_end; // -> Block 4
// Block 3
B;
++i;
goto loop_start;
// Block 4
loop_end:
C;
ここでは、ブロック2の条件は1つだけです。したがって、完全な分岐カバレッジを取得するには、falseとtrueの両方を一度評価する必要があります。テスト計画は次のようになります。
Run 1:
length = 1
# executes B1 B2 B3 B2 B4
したがって、このテスト計画では、ループ条件はtrueとfalseの両方に評価されます。しかし、明らかに、これは満足のいくテストではありません。ループが完全にスキップされるとどうなりますか(例:length = 0
)?ループ本体がいくつかの状態を変更するとどうなりますか?それでも何百回もの繰り返しで動作しますか?
コードを制御フローグラフにグループ化すると、パスカバレッジは、考えられるすべてのパスから取得したパスの割合を測定します。パスカバレッジは、ブランチカバレッジを意味します。最初の例を振り返ると、2つのテストケースのみでブランチカバレッジを取得できました。ただし、パスカバレッジを取得するには、4つのケースが必要です。最初の条件を通過するパスごとに2つ、2番目の条件の2つのケースを掛けたものです。
Run 1:
B = false
F = false
# executes A B _ D E F _ I
Run 2:
B = false
F = true
# executes A B _ D E F G I
Run 3:
B = true
F = false
# executes A B C _ E F _ I
Run 4:
B = true
F = true
# executes A B C _ E F G I
制御フローグラフにループが含まれている場合、一般に無限に多くの可能なパスがあります。場合によっては、ループの反復回数は定数によって制限され、テストすることができますが、一般的にはそうではありません。完全なパスカバレッジは便利ですが到達不可能であるため、他のカバレッジメトリックを使用する傾向があります。
テストを書くとき、ループのフルパスカバレッジを無視する傾向があります(単純な条件文のパスカバレッジは依然として非常に便利です)。ただし、テストのために複数のパスをグループ化して同等クラスにすることができます。0、1、2、および「多数」の反復でコードを実行すると、適切な近似になります。可能なテスト計画:
Run 1:
length = 0
# executes B1 B2 B5
Run 2:
length = 1
# executes B1 B2 B3 B2 B5
Run 3:
length = 2
# executes B1 B2 B3 B2 B3 B2 B5
Run 4:
length = 123
# executes B1 B2 B3 B2 B3 ... B2 B3 B2 B5
線形コードシーケンスとジャンプ-カバレッジなど、ループテストを定量化できる正式なコードメトリックもあります。しかし、私はそれを使用したことがありません。
ループが再帰として表現される場合、ループは明示的ではないため、パスカバレッジから「隠されます」。これは問題ですか?やや。ループはプログラム全体の制御フローグラフにはまだ存在していますが、再帰関数のCFGにはありません。
ただし、再帰的に表現するとループが正しいことを示す方がはるかに簡単です。基本ケースと非基本ケースをテストできます。非ベースケースの各結果はベースケース(既に正しいことが示されています)から構築されているため、関数全体は正しいと推定できます。これは帰納法による証明手法に似ていますが、テストが正当性の証明ではなく、単なる正当性の例です。