このセクションでは、C/C++test を使ったテスト実行からカバレッジ情報を取得する方法について説明します。カバレッジは、単体テストおよびアプリケーション レベルで実行される手動テストと自動テストについて収集できます。
カバレッジの統計を参照すると、現在のテスト スイートのカバレッジを計測し、どのようなテスト ケースの追加が必要かを判断するのに役立ちます。C/C++test は、関数カバレッジ、行カバレッジ、基本ブロック カバレッジ、パス カバレッジ、判断文カバレッジ、単純条件カバレッジ、MC/DC (Modified Condition/Decision Coverage) カバレッジといったさまざまなカバレッジをレポートできます。
このセクションの内容
GUI でのカバレッジ情報の参照
カバレッジ サマリ
単体テスト ケースを実行した後にカバレッジ サマリの情報を参照するには、次の操作を行います。
- [カバレッジ] ビューを開きます。
- 表示されていない場合、[Parasoft] メニューの [ビューの表示] > [カバレッジ] をクリックしてください。
- [カバレッジ] ビューのプルダウン ボタンをクリックし、参照するカバレッジを選択します。
- レポートされるカバレッジの種類については 「カバレッジの種類」 を参照してください。
プロジェクトおよび解析されたすべてのファイルと関数のカバレッジ統計は [カバレッジ] ビューに表示されます。テストの実行後にカバレッジが表示されていない場合、1) カバレッジが有効になっていたかどうか、および 2) 計測するよう設定したカバレッジ タイプを表示しているかどうかを確認してください。表示しているカバレッジ メトリクスはビューのツールバーに示されています。
ツールバーのメニューやボタンを使って、結果をソートしたり検索することができます。
ソース コードでの表示
テストしたファイルをエディターで開くと、カバーされた行は緑色で、カバーされなかった行はピンクでハイライト表示されます。実行不可能な行はハイライト表示されません。
なお、パス カバレッジ ビューにするには関数をダブルクリックする必要があります。
注意
C/C++test が計算できるカバレッジ要素 (パス、ブロックなど) の数には上限があります。特定レベル (関数、ファイル、またはプロジェクト) の実際の要素数が上限の 2147483647 を超えている場合、C/C++test はその要素のレポートに "N/A" を表示します。その場合、[カバレッジ] ビューには [パスがない] や [ブロックがない] などの適切なメッセージが表示されます。
カバレッジからテスト ケースへのトレース
どのテスト ケースがどのカバレッジ要素に関連しているかを知ることは、カバレッジ率を向上させるためにテスト ケースをどのように拡張するかを判断するのに役立ちます。
テスト ケースとカバレッジ要素との関連を参照するには、次の操作を行います。
- コード エディターでカバレッジ要素を選択します。
- C/C++test は、マウス ポインターが置かれている場所ではなく、カーソルがある場所を「選択されている」と見なします。
- マウスの右ボタンをクリックし、[Parasoft] > [C/C++test] > [カバーしたテスト ケースを表示] をクリックします。すべての関連するテスト ケースが [テスト ケース エクスプローラー] ビューでハイライト表示されます。
特定のテスト ケースのカバレッジ データ
[テスト ケース エクスプローラー] ビューでテスト ケースを選択します。
- [テスト ケース エクスプローラー] ビューで、カバレッジを解析するテスト ケースを選択します (複数のテスト ケースを選択できます)。
- テスト ケース エクスプローラーはデフォルトで開いています。表示されていない場合にこのビューを開くには、[Parasoft] メニューの [ビューの表示] > [テスト ケース エクスプローラー] をクリックします。[テスト ケース エクスプローラー] ビューの詳細については、「GUI の概要」を参照してください。
- [カバレッジ] ビューで、[テスト ケース エクスプローラーの選択と同期] ボタンをクリックします。
選択したテスト ケースについてだけカバレッジ統計が表示されます。ソース コードについても、選択したテスト ケースに対応する箇所だけがハイライト表示されます。
ヒント: ツールバーとメニューを利用したカバレッジ参照
[カバレッジ] ビューのツールバーとメニューはカバレッジ情報を参照するのに役立ちます。
ツールバー右側のボタンを使用すると、結果を折りたたみ、削除、検索できるほか、テスト ケース エクスプローラーと現在の選択を同期できます。
次のツールバー ボタンを使用すると、カバーされた要素の表示/非表示、縮小表示、削除、および検索を行うことができます。
メニュー コマンドを使用すると、名前またはカバレッジを基準にしてカバレッジ結果をソートできるほか、目的のカバレッジ タイプを選択できます。
注意: 開始時の [カバレッジ] ビューの結果
パフォーマンスを最適化するために、[カバレッジ] ビューは未初期化モードで開始し、プロジェクト レベルのカバレッジ サマリだけが表示されます。未初期化モードは、グレー表示のプロジェクト アイコンで示されます。
未初期化モードのカバレッジは、現在のものではない可能性があります。たとえば、この IDE の外でコードが変更された場合などです。[カバレッジ] ビューはプロジェクト ノードを展開するだけで更新できます。または、実行中に [カバレッジ] ビューが自動的に更新されるのを待つこともできます。
レポートでのカバレッジ情報の参照
レポートを設定、生成、参照する方法の詳細については、「結果の参照」を参照してください。
カバレッジの種類
C/C++test は次のカバレッジをサポートします。
- 行カバレッジ
- ステートメント カバレッジ
- ブロック カバレッジ
- パス カバレッジ
- 判断文カバレッジ
- Modified Condition/Decision Coverage (MC/DC)
- 単純条件カバレッジ
- 関数カバレッジ
- コール カバレッジ
次の表を参照して用語を確認してください。これらのカバレッジを C/C++test がどのように扱うかを理解するのに役立ちます。
用語 | 説明 |
---|---|
基本ブロック | 一連の分岐していないステートメント。制御の流れにおいて分岐がない、一連の線形のコード。 |
パス | 関数に入ってから抜けるまでの一連の固有な基本ブロック。 |
判断文/ ブランチ | 判断文/ブランチは、コード中の分岐点で取られる、可能性のある制御フローの「判断文」。C/C++test は、if-else、for、while、do-while、および switch 命令を分岐点と見なします。例外ハンドラー (throw-catch 文) などの動的な分岐点は考慮されません。 |
論理式 | C++ では、論理式は単純に bool 型を持つ式です。 C 言語では、C/C++test は次のものをブール演算式として扱います。
「C++ テンプレート内のブール式の計算」も参照してください。 |
MC/DC Decision | 条件および 0 個以上の論理演算子から構成される最上位レベルの論理式。C/C++test は、コンストラクター イニシャライザーと関数のデフォルト引数を除き、ソース コード中のすべての非定数の論理式について MC/DC および SCC を計測します。 |
条件 | MC/DC Decision の一部であるアトミックな非定数の論理式。 MC/DC Decision の部分式の中に論理演算子 (&&, ||, !) がない場合、部分式は条件と見なされます。 特定のアトミックな式が 1 つの条件中に 2 回以上出現している場合、各オカレンスは異なる条件です。 |
関数カバレッジ
実行中に少なくとも 1 回到達された関数の数を示します。すべての関数が少なくとも 1 回到達される場合、完全な 100% の関数カバレッジが取得されます。
コール カバレッジ
プログラム実行時にどれだけ定義済み関数またはメソッドが呼び出されたかを示します。コール カバレッジ が100% の場合、すべての関数またはメソッドが呼び出されたことを示します。
制限:
- 明示的または暗黙的コンストラクターの呼び出しは、コール カバレッジの計算には含まれません。
- 暗黙的デストラクターの呼び出しは、コール カバレッジの計算には含まれません。
- 事前定義またはオーバーロードされた C++ 演算子はコール カバレッジの計算には含まれません。
例:
class A { public: A() {} A(const A&) {} A(int val) {} A& foo() { return *this; } ~A() {} }; void funcA(const A& a) {} A& operator+(const A & a, const A & b) {} void defaultConstructorCall() { A objA; // Default constructor call - not included A objArr[10]; // Default constructor calls - not included A objB = objA; // Copy constructor call - not included A objC = 10; // Implicit call of A(int) constructor - not included funcA(10); // Implicit call of A(int) constructor - not included A res = objA + objA; // Operator + call - not included // Copy constructor call - not included A* objD = new A(); // Default constructor call - not included // Operator new call - not included delete objD; // Destructor call - not included // Operator new call - not included A* objE = new A[10]; // Default constructor calls - not included // Operator new call - not included delete[] objE; // Destructor calls - not included // Implicit destructor calls - not included }
行カバレッジ
ソース コード中の実行可能な行について、制御の流れが最低 1 回達した行の数を示します。 すべての実行可能な行に制御の流れが最低 1 回達した場合、行カバレッジは 100% です。
ステートメント カバレッジ
少なくとも 1 回制御フローによって到達された、実行可能なソース コードのステートメントの数を示します。実行可能なすべてのステートメントが少なくとも 1 回到達される場合、完全な 100 % のカバレッジが取得されます。
ブロック カバレッジ
ブロック カバレッジは行カバレッジに関連するメトリクスです。ただし、ブロック カバレッジが測定するコード単位は「基本ブロック」です。用語の定義を前ページの表で確認してください。ブロック カバレッジは、ソース コード中の基本ブロックについて、制御の流れが最低 1 回達したブロックの数を示します。
パス カバレッジ
パス カバレッジは、関数中の可能な各パスについて制御フローが通ったかどうかをチェックします。 パスを特定するために使用される分岐点は、行カバレッジの場合と同じです。「パス」という用語については、前述の表を参照してください。
ループは無限のパスを生み出します。そのため、パス カバレッジの測定は、制限された数のループの可能性だけを考慮します。while ループと for ループ場合、「0 回 の反復」と「1 回以上の反復」の 2 つの可能性を考慮します。
シグナルまたは呼び出し先関数からスローされた例外などの特殊な状況から発生する実行パスは、可能性のある実行パスのセットには含まれません。そのようなパスが実行時に実際に起こった場合、「予期しない」パスとしてカウントされ、レポートされます。
ソース コード エディターでは、一度に 1 つのパスがハイライト表示されます。ソース コード エディターでパスを参照するには、[カバレッジ] ビューで適切な関数ノードをダブルクリックします。 関数のパスからパスに移動するには、[カバレッジ] ビューのツールバーの [次の要素をハイライト] および [前の要素をハイライト] ボタンを使用します。
カバーされていないパスだけを表示するには、[カバレッジ] ビューのツールバーの [カバーされていない要素をハイライト] ボタンをクリックします。逆に、カバーされた要素だけを表示するには、[カバーされた要素をハイライト] ボタンをクリックします。なお、[カバーされていない要素をハイライト] ボタンがオフの場合にだけ、[次の要素をハイライト] および [前の要素をハイライト] ボタンは予期せぬパスを反復します。
判断文カバレッジ
判断文 (Decision) カバレッジは、制御フローが通過したソース コード中の分岐の数を示します。各「判断文」がすべての分岐点ですべての可能な出力を少なくとも 1 回得た場合、判断文カバレッジは 100% になります。
ソース コード中の分岐点と見なされるのは次のステートメント タイプです。
if-else、
for
、while
、do-while
、switch
例外ハンドラー (throw-catch
文) などの動的な分岐点は考慮されません。
ファイル中に「判断文」がない場合、C/C++test は判断文カバレッジが使用不可であることを "N/A" というラベルでレポートします。
Modified Condition/Decision Coverage (MC/DC)
MC/DC は、国際技術標準 DO-178B/C (RTCA) に準拠しています。これは、ソフトウェア証明のための基準を指定したものであり、対象となるソフトウェアには、航空業界で使用される重要機器およびシステムのためのリアルタイム組込みシステムも含まれます。
DO-178B/C に従うと、完全な (100% の) MC/DC カバレッジを得るには、次の 3 つの条件を満たす必要があります。
- 各「判断文」 が、少なくとも 1 回すべての可能な結果を得ている。
- 1 つの「判断文」 中の各条件が、少なくとも 1 回すべての可能な結果を得ている。
- 1 つの「判断文」 中の個々の条件が、単独で全体の「判断文」 の結果を左右する。
C/C++test では、MC/DC カバレッジについて各条件と各「判断文」 が 2 つの結果 ( true または false ) しか持てないと見なしているため、3 番目の条件 (c) だけがチェックされます。なぜなら、(c) は条件 (a) および (b) を内包するからです。条件は、その特定の条件だけを変えつつ他のすべての可能な条件を固定することによって、全体の「判断文」 の出力に独立して影響するように示されます。そのため、1 つの条件をテストするために、C/C++test は次のようなテスト ケースを探します。
- そのテストされた条件が true と false の両方の結果を得る。
- 「判断文」 中の他の条件が変わらない (または C/C++ の演算子が短絡論理であるため評価されない)。
- 「判断文」 の結果が変わる。
したがって、MC/DC 率は次の式を使って計算されます。
MC/DC[%] = m/n
ここで、m
は 「判断文」 の結果に個々に影響する論理条件の数であり、n
は 1 「判断文」 中の条件の総数です。
1 つの条件が実行されるようにするには、少なくとも 2 つのテスト ケースが実行される必要があります。true
に評価される条件があるテスト ケースと、false
に評価される条件があるテスト ケースです。
「C++ テンプレート内のブール式の計算」も参照してください。
MC/DC の例
たとえば、次のコードを考えてみましょう。
if (a && (b || c)) // [...]
a、b、および c という3 つの単純な条件があります。結果として、MC/DC 式の m/n における n は、3 に等しくなります。
ここで、次のテスト ケースが実行されたとしましょう。
id | a | b | c | a && (b || c) |
---|---|---|---|---|
1 | true | true | false | true |
2 | false | true | false | false |
3 | true | false | false | false |
MC/DC カバレッジを計測するために、C/C++test は次のテスト ケースの組合せを探します。1) 「判断文」が異なる値に評価された。 2) 1 つの条件の値だけが変化している (他のすべての条件は変わっていない)。
この例では、a の値を独立して変更することが完全な「判断文」の値に影響している組合せが 1 つあります。
id | a | b | c | a && (b || c) |
---|---|---|---|---|
1 | true | true | false | true |
2 | false | true | false | false |
もう 1 つの組合せは、b の値を独立して変更することが完全な「判断文」の値に影響することを示します。
id | a | b | c | a && (b || c) |
---|---|---|---|---|
1 | true | true | false | true |
3 | true | false | false | false |
これは、完全な「判断文」の値に a と b が独立して影響することをテスト ケースが証明したことを意味します。MC/DC カバレッジに関して言えば、a と b はカバーされるが、条件 c はカバーされません。
C/C++test はそのような例について 67% [2/3 の条件がカバー] の MC/DC カバレッジをレポートします。条件にカーソルを置くと、条件と判断文が評価された実際の値がツールチップに表示されます。
単純条件カバレッジ
単純条件カバレッジは、すべての「判断文」の条件の結果に対するカバレッジを表示します。1 つの 「判断文」中の条件の数を n とした場合、1 つの「判断文」に対する結果の数は 2 * n になります。したがって、100% のカバレッジを得るには、すべての条件がすべての可能な結果を取らなければなりません。ただし、ある条件が 1 つの結果 (真または偽) を取るだけで、0 以外のカバレッジが取得されます。
「C++ テンプレート内のブール式の計算」も参照してください。
各条件はブール条件です。条件が true と false の両方に評価される場合、条件は緑でマークされます。true または false のいずれかに評価される場合、黄色でマークされます。true にも false にも評価されない場合、ピンクでマークされます。
条件にカーソルを置くと、条件が評価された実際のブール値がツールチップに表示されます。
C++ テンプレート内のブール式の計算
判断文内の副式の型が C++ テンプレート パラメーターに依存する場合、C/C++test は副式がさらにブール型の副式に分解されることはないと仮定します。これは、テンプレート パラメーターの実際の型は、ブール型と互換性がない (または型が異なれば分解が異なる) 可能性があるからです。これは、式全体がどのように判断文および条件に分解されるかに影響を与える可能性があります。
次のサンプルを参照してください:
struct D { operator bool() { return false; } }; struct E { bool operator||(const bool& b) { return b; } }; template<typename T> void example(bool a, bool b, D d, E e, T t) { if (a || b) {} // a || b // 1 decision ('a || b'), with 2 conditions ('a' and 'b') if (d || b) {} // d || b // 1 decision ('d || b'), with 2 conditions ('d' and 'b') if (e || b) {} // operator||(e, b) // 1 decision ('operator||(e, b)'), with 1 condition ('operator||(e, b)') // not decomposable ('E' cannot be converted to 'bool') if (t || b) {} // operator||(t, b) // 1 decision ('operator||(t, b)'), with 1 condition ('operator||(t, b)') // assumed not decomposable ('T' may be 'E') if (a || b || t) {} // operator||(a || b, t) // 2 decisions: // * decision 'operator||(a || b, t)', with 1 condition ('operator||(a || b, t)') // assumed outer OR is not decomposable ('T' may be 'E') // * decision 'a || b', with 2 conditions ('a' and 'b') }
カバレッジ率の増加
カバレッジ率を上昇させるための方法については 「テスト カバレッジの増加」を参照してください。