よくある質問(FAQ)

インライン展開された関数やマクロ定義された関数をテストしたいのですが、どのようにするのが良いでしょうか?

テスト対象について

質問

#pragmaやinlineキーワードによってインライン展開される関数や、マクロ定義された関数を単体テストしたいのですが、どのようにすれば良いですか?

回答

カバレッジマスターで関数をテスト対象とするには、デバッグ情報(シンボル)を保持した関数オブジェクトとしてコードが生成されている必要があります。インライン展開の指定やマクロ定義で記述された処理を、関数名を直接指定してテストしたりスタブ化したりする場合、それらの指定を外して「通常の関数」としてオブジェクト化しなければなりません。ただし、この手法では実際の製品コードとオブジェクト構造が異なってしまう点に注意が必要です。

<テストの考え方について>
インライン関数やマクロ定義されたサブ関数は、呼び出し元の関数内にコードが埋め込まれ、一つの関数オブジェクトとして構成されます。したがって、これらを分離せずにそのままの状態でテストを行うことが、実際の製品コードに最も忠実なテストとなります。

以下に、インライン関数およびマクロ定義されたサブ関数をテストする際の、それぞれの考え方を示します。

■マクロ記述された関数

マクロ定義されたサブ関数は、呼び出し元の関数内では単一の処理(1行の実行文)として扱われるため、その内部のカバレッジを個別に測定することはできません。マクロ内部のカバレッジ計測や、CSVから直接データを入力してテストを行いたい場合は、マクロ定義を解除し、通常の関数としてコンパイルする必要があります。
1つの方法として、実機コードに近い「マクロが埋め込まれた状態」でテストを実施してください。その上で、追加の検証としてマクロ定義を関数オブジェクト化し、マクロ部分のみの単体テストおよびカバレッジ計測を行う「2段階のテスト」を推奨いたします。

testfunc() // テスト対象関数

{

  subfunc(); // マクロ定義された関数 ←subfunc()内部のカバレッジは計測できない

}

subfunc()
{
  :
}
を単独でテストしたりカバレッジ計測をするためには、マクロ定義を外す必要がある

マクロ定義を解除して関数化したことにより、テスト対象関数全体の機能に影響がないことを保証するためには、マクロ化の「有無」によるテスト結果(出力値)の一致を確認することを推奨いたします。具体的には、同一の入力データを用いて、マクロ状態と関数オブジェクト化状態の両方でテストを実行し、期待値通りの結果が得られるかを比較検証してください。

testfunc() // テスト対象関数

{

  subfunc(); // マクロ定義された関数

}
testfunc() // テスト対象関数

{

  subfunc(); // マクロ定義を外した関数

}

上記2つのtestfunc()テスト結果が同じであることを確認することで、マクロ化の有無の影響が無いことを確認できる

■インライン化された関数

コンパイラの最適化やインライン指定によってインライン展開されたサブ関数は、テスト対象の関数を実行した際、「埋め込みコードによるC0カバレッジ計測」を適用している場合に限り、その内部のカバレッジも同時に測定されます。

ただし、この状態のサブ関数は独立した関数オブジェクトを持たないため、スタブ化やCSVファイルから直接データを与えての単体テストは行えません。

また、埋め込みコードを適用しない通常の計測では、マクロ定義の場合と同様にサブ関数内部のカバレッジ測定は行えません。
これらの詳細な検証を行うには、インライン展開を解除し、通常の関数としてコンパイルする必要があります。

testfunc() // テスト対象の関数

{

  subfunc(); // インライン化された関数 ←subfunc()内部のカバレッジも計測される

}

ただし、

subfunc()
{
  :
}
を単独でテストするためには、インライン化を外す必要がある

インライン化を解除して関数化したことにより、テスト対象関数全体の機能に影響がないことを保証するためには、インライン化の「有無」によるテスト結果(出力値)の一致を確認することを推奨いたします。具体的には、同一の入力データを用いて、インライン状態と関数オブジェクト化状態の両方でテストを実行し、期待値通りの結果が得られるかを比較検証してください。

testfunc() // テスト対象関数

{

  subfunc(); //インライン化された関数

}
testfunc() // テスト対象関数

{

  subfunc(); // インライン化を外した関数

}

上記2つのtestfunc()テスト結果が同じであることを確認することで、インライン化の有無の影響が無いことを確認できる