このトピックでは、動的スタブ設定でスタブ コールバックを使用する方法を説明します。
このセクションの内容
概要
スタブ コールバックは、テスト固有のスタブ ロジックをプログラミングするための強力なメカニズムです。テスト ケースごとに固有のスタブの動作を定義し、テスト ケース実行時にスタブが呼び出されるたびに実行できます。C++test はテスト ケース固有のスタブ ロジックを実行するコードを自動生成するため、メインのスタブ定義を変更する必要はありません。
以下のいずれかの方法でスタブ コールバックを設定できます。
- テスト ケース エディターの UI を使用する (「テスト ケース エディターでのスタブ動作の設定」を参照)
- テスト ケースのソース コードを手動で変更する (「ソース コードでのスタブ動作の設定」を参照)
テスト ケース エディターは、スタブ コールバック フレームワークのカスタマイズ可能なコンポーネントを自動生成し、スタブ設定に関する提案を表示し、作成済みのスタブ コールバックを登録します。
スタブ コールバックのクイック スタート
スタブ コールバックを使用するには、スタブを作成する前に、スタブ ビュー (「[スタブ] ビューでのスタブの参照」を参照) またはテスト コンフィギュレーションで直接的に (「[実行] タブ - テストの実行方法を定義する」を参照) [スタブ コールバックの有効化] オプションが有効化されている必要があります。
テスト ケース エディターでのスタブ動作の設定
- [自動スタブの生成] または [ユーザー スタブの作成] オプションを使用して設定対象の関数にスタブを作成します (「スタブの追加と変更」を参照)。
- テスト ケース エディターでテスト ケースを開きます。
- 新規 Stub Configuration ステップを追加し、設定対象の関数を指定します。
- 利用可能なアクションおよび入力/出力パラメーターを使用してスタブのロジックを定義します。
- テスト ケースを実行します。テスト ケースが実行されると、スタブ設定ステップで定義されたカスタム スタブ ロジックがスタブ呼び出し時に実行されます。
テスト ケース エディターを使用したスタブ動作の設定の詳細については「テスト ケース エディターによるテスト スイートとテスト ケースの追加」を参照してください。
ソース コードでのスタブ動作の設定
[自動スタブの生成] または [ユーザー スタブの作成] オプションを使用して設定対象の関数にスタブを作成します (「スタブの追加と変更」を参照)。
- コード エディターでテスト スイート ファイルを開きます。
テスト スイート ファイルにスタブ コールバック関数を追加します。
利用可能な入力/出力パラメーターを使用して、スタブ コールバック関数にスタブ ロジックを定義します。
テスト ケース定義に移動し、次のマクロを使用してスタブ コールバックを登録します:
CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>)
テスト対象関数が呼び出される前にコールバックが登録されることを確認してください。
- テスト ケースを実行します。テスト ケースが実行されると、設定したスタブ ロジックがスタブ呼び出し時に実行されます。
スタブ コールバック関数およびスタブ コールバックの登録の詳細については、「スタブ コールバックの詳細」を参照してください。
スタブ コールバックの詳細
スタブ コールバック フレームワークは、以下の要素で構成されます。
- スタブ コールバック関数: 個々のスタブのためのカスタム スタブ ロジックを実装するユーザー定義関数です。
- スタブ コールバック登録: スタブ コールバック関数をアクティベートするメカニズムです。通常、テスト ケースの内部に置かれます。
- スタブ コールバック実行: スタブ コールバック関数の呼び出しです。C++test のスタブ定義に組み込まれます。
スタブ コールバック関数
スタブ コールバック関数は、ユーザー定義の C/C++ 関数であり、関連するスタブが呼び出されたときに実行されるロジックを含んでいます。スタブ/スタブ化される関数から派生した一意のシグニチャを持ちます。
void <CALLBACK_NAME>(CppTest_StubCallInfo* stubCallInfo, <STUB_IN_OUT_PARAMETERS>)
スタブ コールバック関数のインターフェイスには、スタブされる関数のすべての入力/出力パラメーター (<STUB_IN_OUT_PARAMETERS>
) が含まれるほか、追加のヘルパー パラメーター (stubCallInfo
) が含まれます。コールバック関数の名前 (<CALLBACK_NAME>
) をカスタマイズすることもできます。
次のサンプルは、int processValues(int i, int j);
関数のスタブ コールバック関数をカスタマイズする方法を示しています。
void CppTest_StubCallback_processValues_case_1(CppTest_StubCallInfo* stubCallInfo, int* __return, int i, int j) { // checking input value CPPTEST_ASSERT_INTEGER_EQUAL(-1, i); // modifying return value *__return = 150; }
スタブ コールバック関数と関連するテスト ケースの定義は、同じテスト スイート ファイル内にまとめておくことを推奨します。
スタブ コールバック関数は、グローバル関数またはテスト スイート クラスの静的メンバー関数 (C++ の場合のみ) として定義できます。そのため、[private メンバーにアクセス] インストゥルメント機能が有効化されている場合、スタブ コールバック関数はテスト対象コードのプライベート クラスにアクセスできます。
カスタム スタブ ロジックは、以下のスタブ コールバック インターフェイスを使用して、任意の有効な C または C++ コードを用いて表現できます。
- スタブ化される関数のパラメーター - スタブ コールバック関数のパラメーターとして利用可能
- スタブ化される関数の戻り値 - 戻り値のホルダーを指す "
__return
" ポインターとして利用可能 - スタブ化される関数のクラス オブジェクト - クラス オブジェクトを指す "
__this
" ポインターとして利用可能 - その時点でスタブ コールバック関数が呼び出された回数 - "
int stubCallInfo->callNo
" 変数として利用可能
また、スタブ コールバック関数内では、C++test 単体テスト API を含めたグローバル変数またはグローバル関数を使用することもできます (CPPTEST_ASSERT
および CPPTEST_REPORT
など)。スタブ化される関数のオリジナルの定義が利用可能な場合、スタブ コールバック関数からオリジナルの関数を呼び出すこともできます。
1 つのテスト スイート ファイル内に複数のスタブ コールバック関数を定義できます - 1 つのスタブに対応する複数のコールバック関数を定義することも、別個のスタブに対応するコールバック関数を定義することもできます。
1 つのスタブ コールバック関数は、単一のテスト ケースでだけ使用することも、複数のテスト ケースで共有することもできます。
1 つのスタブは、1 度に 1 つだけアクティブなスタブ コールバック関数を持つことができます (「スタブ コールバックの登録」を参照)。
スタブ コールバックの登録
スタブ コールバック関数をアクティブにするには、登録する必要があります。通常、関数は、スタブ化される関数が最初に呼び出される前に、関連するテスト ケース内で登録されます。多くの場合、テスト対象関数の呼び出しの前に登録を置くべきです。
スタブ コールバック関数を登録するには、次の API 呼び出しを使用します。
CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>)
パラメーターの意味:
<STUB_ID>
は一意のスタブ識別子です (「スタブ コールバックの実行」を参照)<STUB_CALLBACK_NAME>
はユーザー定義のスタブ コールバック関数の名前です。
例:
CPPTEST_REGISTER_STUB_CALLBACK("processValues", &CppTest_StubCallback_processValues_case_1);
1 つのスタブ コールバック関数を複数のテスト ケースで登録できます。そうすると、それぞれの関数は該当スタブの同じカスタム ロジックを使用します。また、1 つのテスト ケース内で (複数のスタブに対応する) 複数のスタブ コールバック関数を登録することもできます。これにより、1 つのテスト ケースで複数のスタブにカスタム動作を提供できます。任意の時点で、特定のスタブにはアクティブなスタブ コールバック関数が 1 つだけ存在することができます。
スタブ コールバック関数のライフサイクルは次のとおりです。
- アクティベーション:
CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>)
による登録 - デアクティベーション: テスト ケースの終了または同じスタブ (同じ
<STUB_ID>
) に対する別のスタブ コールバック関数の登録
例:
void test_case_1() { ... // CppTest_StubCallback_foo activation: CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo); // CppTest_StubCallback_bar activation: CPPTEST_REGISTER_STUB_CALLBACK("bar", &CppTest_StubCallback_bar); ... callToFunctionUnderTest(); // will call foo() and bar() ... } // end of test case: CppTest_StubCallback_foo deactivation, CppTest_StubCallback_bar deactivation void test_case_2() { ... // CppTest_StubCallback_foo activation: CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo); // CppTest_StubCallback_bar activation: CPPTEST_REGISTER_STUB_CALLBACK("bar", &CppTest_StubCallback_bar); ... callToFunctionUnderTest(); // will call foo() and bar() ... // CppTest_StubCallback_foo_1 activation, CppTest_StubCallback_foo deactivation CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo_1); } // end of test case: CppTest_StubCallback_foo_1 deactivation, CppTest_StubCallback_bar deactivation
スタブ コールバックの実行
スタブ コールバック関数が定義・登録済みである場合、対応するスタブが呼び出されるたびにコールバック関数が実行されます。コールバック関数は、
を呼び出すことで実行されます。これは、スタブ作成時に [スタブ コールバックの有効化] オプションが有効である場合 (このオプションはデフォルトで有効です)、自動的にスタブ定義に追加されます。CPPTEST_CALL_STUB_CALLBACK()
例:
/** Auto-generated stub definition for function: int processValues(int, int) */ int processValues (int i, int j) ; int CppTest_Auto_Stub_processValues (int i, int j) { CPPTEST_STUB_CALLED("processValues"); int __return = 0; /** * This section enables Dynamic Stub Configuration with Stub Callbacks. * * IMPORTANT: THIS COMMENT BLOCK SHOULD NOT BE DELETED OR MODIFIED * * 1. Define stub callback function in test suite file - use the following signature: * void CppTest_StubCallback_SomeName(CppTest_StubCallInfo* stubCallInfo, int* __return, int i, int j) * * 2. Register stub callback in test case function - use the following code: * CPPTEST_REGISTER_STUB_CALLBACK("processValues", &CppTest_StubCallback_SomeName); * * 3. Fill out the body of the stub callback function according to intent. * The following line may be used to call original function inside stub callback: * *__return = ::processValues(i, j); */ if (CPPTEST_STUB_HAS_CALLBACK()) { CPPTEST_STUB_CALLBACK_PARAMS(int* __return, int i, int j); CPPTEST_STUB_INVOKE_CALLBACK(&__return, i, j); } else { /* You can put additional stub logic here. */ } return __return; }
スタブ定義に自動的に追加されるスタブ コールバックの呼び出しセクションには、スタブ コールバック関数の完全なシグニチャとスタブ コールバックの登録のサンプル行が含まれるので、手動でスタブ コールバックを設定する際にテスト スイート ファイルにコピーして使用できます。
スタブ識別子
スタブ コールバックの登録および実行に使用されるスタブ識別子は、スタブ固有の識別子でなければなりません。デフォルトでは、C++test によって生成されたスタブは、次のパターンに従った識別子を使用します。
[<parent::>]<function_name>
<parent::>
接頭辞は、スタブ化される関数がクラスまたは名前空間のメンバーである場合にだけ付加されます。直接の親だけが追加されます。テンプレート クラス メソッドの場合、親の名前のテンプレート パラメーターは省略されます。
オーバーロードされた関数に対するスタブ コールバックの使用
C/C++test は、関数のすべてのオーバーロードに同じスタブ識別子を使用します (「スタブ識別子」を参照)。オーバーロードされた関数に対してスタブ コールバックを使用する前に、スタブ コールバック実行コード (CPPTEST_CALL_STUB_CALLBACK()
) およびスタブ コールバック登録の識別子を変更し、識別子がユニークになるようにします。そうすれば、オーバーロードされた関数/メソッドに対してスタブを区別することができます。
例:
foo() のオーバーロードされたバージョンで使用されるデフォルトの識別子
CPPTEST_STUB_CALLED("foo");
foo(int) 用に変更された識別子
CPPTEST_STUB_CALLED("foo_int")
オリジナルの関数を呼び出すスタブの作成
テスト ケース固有のスタブ コールバック関数がテスト ケースに登録されていない場合にオリジナルの関数を呼び出すスタブを生成できます。それには、スタブ ビュー (「 [スタブ] ビューでのスタブの参照」を参照) またはテスト コンフィギュレーションで次のオプションを有効にします (「[実行] タブ - テストの実行方法を定義する」を参照)。
- スタブ コールバックの有効化
- オリジナルの関数への呼び出しを挿入
これらのオプションを有効にすると、以下のスタブ ストラテジが適用されます。
- 実行されるテストにテスト ケース固有のスタブ コールバックが登録されている場合、スタブ コールバック関数を使用してオリジナルの関数をスタブ化します。
- 実行されるテストにテスト ケース固有のスタブ コールバックが登録されていない場合、オリジナルの関数を呼び出します。結果として、テスト ケース実行時にオリジナル関数が呼び出され、スタブは「プロキシ」として動作します。
- 実行されるテストにテスト ケース固有のスタブ コールバックが登録されておらず、オリジナルの関数が利用できない場合、スタブに定義されたカスタム ロジックを使用します。
例:
以下のものについては、オリジナル関数の呼び出しはサポートされていません。
- コンストラクター
- 可変引数リスト (...) を持つ関数
- 純粋仮想関数
- 内部リンケージを持つ関数
- 戻り値型の推論が行われ、ヘッダーが参照できない関数