このセクションでは、テスト中にアクセスできないリソースのためにユーザー定義スタブを使用する方法と、自動生成スタブを変更する方法について説明します。
このセクションの内容 :
注意
- スタブを使用する場合は、テスト コンフィギュレーションの [実行] > [全般] タブで [インストゥルメント モード] 設定を [完全]、[カバレッジ計測なし (スタブあり)]、スタブ インストゥルメントを含むカスタム インストゥルメントのいずれかに必ず設定してください。
- C++test では、スタブの優先順位が次の順序で定められています。
ユーザー定義スタブ、自動生成セーフ スタブ、オリジナル関数、自動スタブ
したがって、自動生成スタブが使用されるのは、他の定義 (ユーザー定義スタブまたはオリジナル関数) が使用できない場合だけです。 - C++test は、コードまたはライブラリ中にオリジナルの定義がある場合、デストラクターをスタブ化しません。デストラクターの C++test 生成スタブが使用されるのは、オリジナルのデストラクターが使用できない場合だけです。
概要
「スタブ」を参照してください。
[スタブ] ビューでのスタブの参照
[スタブ] ビューは、最後に実行した単体テスト コンフィギュレーションに基づいてスタブ コンフィギュレーションの詳細を表示します。[スタブ] ビューでは、見つからないシンボルに対してユーザー定義スタブまたは自動生成スタブを作成して、スタブ コンフィギュレーションを変更することができます。
[スタブ] ビューへのアクセス
[スタブ] ビューにアクセスするには、次の操作を行います。
- [Parasoft] メニューの [ビューの表示] > [スタブ] をクリックします。
注意
- [スタブ] ビューを初めて表示したときは、ビューは空です。「シンボル データが収集されませんでした」というメッセージが表示されます。
[スタブ] ビューについて
[スタブ] ビューには以下の列を持つテーブルが表示されます。
- シンボル 関数またはグローバル変数の名前です。
- 定義 現在の定義 (スタブ)の種類です。
- ユーザー ユーザーが作成した定義 (スタブ) が使用されます。
- セーフ C++test のセーフ定義 (スタブ) が使用されます。
- オリジナル オリジナルの定義が使用されます。
- 自動 C++test の自動定義 (スタブ) が使用されます。
- なし (不要) 定義はありません。リンカーは定義を必要としません。
- なし 定義はありませんが、リンカーは定義を必要としています。多くの場合、この状態はテスト実行可能ファイルをビルドした場合にリンカー エラーを引き起こします。
- 場所 現在の定義 (ソース ファイル、ライブラリ) の場所です。見つからない場合は N/A です。
[スタブ] ビューの更新
[スタブ] ビューの内容は、単体テスト中に収集されたデータに基づいて更新されます。またユーザー スタブの作成や自動スタブの作成などの [スタブ] ビューから実行できる特定のアクションの結果として更新されます。[スタブ] ビューの内容は、手動でのスタブの追加または削除などの外部のアクションによっては更新されないことに注意してください。
未使用の定義
[スタブ] ビューには、最後に使用されたスタブの設定に関する情報とともに、他の利用可能だが使用されなかった定義の情報も表示されます。たとえば、ユーザー スタブが定義されている関数の場合、既存のオリジナルの定義も表示されます。このような未使用の定義の [定義] 列には、"(未使用)" と表示されます (例: "Original (not used)")。未使用の定義を非表示にするには、[スタブ] ビューのツール バーの [フィルター] ボタンをクリックし、[使用されていない定義を非表示] をオンにします。
複数の定義
1 つの関数に 2 つ以上のスタブ定義がある場合 (たとえば、特定の関数に対して 2 つのユーザー スタブ定義がある場合など)、[スタブ] ビューに複数の定義が表示されます。スタブ アイコンの上にエラーを表すマークが付けられ、[定義] 列に "(コンフリクト)" と表示されます (例: " User (conflict)
")。
シンボル データの収集とリフレッシュ
シンボル データを収集またはリフレッシュするには、次の操作を行います。
- プロジェクト ツリーでテスト対象のファイルを選択します。
- テスト実行可能ファイルをビルドするテスト コンフィギュレーション (たとえば Collect Stub Information または Build Test Executable など) を実行します。
[スタブ] ビューの使用のヒント
- コード エディターでシンボル定義 (スタブ) の箇所に移動するには、対応するテーブルの行をダブルクリックします。または、行を右クリックしてショートカット メニューの [移動] をクリックします。このメニューは、定義が含まれるファイルが現在のプロジェクトの一部である場合にだけ利用できます。
- スタブ定義が含まれるファイルを削除するには、テーブルでファイルを選択し、ショートカット メニューの [スタブ ファイルを削除] をクリックします。ファイルに含まれるすべてのスタブ定義が削除されます。
- テーブルを列の値でソートするには、列のヘッダーをクリックします。
- テーブルの内容を検索するには、テーブルを右クリックしてショートカット メニューの [検索] をクリックし、検索条件を指定します。
ウィザードによって生成されたスタブ ファイルへのユーザー定義スタブの追加
ウィザードでスタブ ファイルを生成し、それを編集することによってユーザー定義スタブを追加するには、次の操作を行います。
- 新しいスタブのディレクトリを作成します (まだこの操作を行っていない場合)。
- スタブのディレクトリはプロジェクト内のどこにあってもかまいません。デフォルトでは、C++test はプロジェクトの stubs サブディレクトリにスタブがあると仮定します。しかし、テスト コンフィギュレーション設定画面の [実行] > [シンボル] タブの [次の場所で発見されたファイルのシンボルも使用] フィールドでスタブの場所を変更すれば、デフォルトとは異なる場所を使用することができます。
- 次のいずれかの方法でスタブ ウィザードを開きます。
- [スタブ] ビューでスタブを作成する関数を右クリックし、[ユーザー スタブを作成] をクリックします。
プロジェクト ツリーでスタブのディレクトリを選択し、
[C++test] メニューの [ウィザード] > [新規ユーザー スタブ ファイルの作成...] をクリックします。ウィザードが開きます。ウィザードの関数テーブルでスタブを作成する関数を選択し、[次へ] をクリックします。
注意
- 「シンボル データが収集されませんでした」という警告は、必要なシンボル データがまだ収集されていないことを表しています。シンボル データの収集/更新の詳細については 「シンボル データの収集とリフレッシュ」を参照してください。
- 「No symbols to create stubs for」という警告は、ユーザー定義スタブを作成できる関数がないことを表しています。
- [カスタム スタブ ウィザード] ダイアログで新規スタブ ファイルの名前と場所を入力します。ユーザー定義スタブ ファイルが作成され、コード エディターで開かれます。ファイルには適切な定義と必要な #include ディレクティブが自動的に追加されます。
- [終了] をクリックします。スタブ ファイルが自動的にエディターで開かれます。
- スタブの定義や #include ディレクティブを確認し、必要に応じて変更します。
- 変更したファイルを保存します。
注意
ユーザー定義スタブには以下の特徴があります。
- 複数の関数のスタブを 1 度に作成できます。テーブルで複数の関数を選択し、選択を右クリックして [ユーザー スタブを作成] ショートカット メニューをクリックします。すべてのユーザー定義スタブが同じスタブ ファイルに追加されます。
- 任意の関数のスタブを作成できます。
- ユーザー定義スタブの優先度は最高です。オリジナルの定義が利用可能な場合でも、ユーザー定義スタブが使用されます。
- グローバル変数に対しては作成できません。代わりに自動スタブを使用するべきです。
ヒント
- 特定のライブラリのすべての関数に対してスタブを素早く作成する場合、テーブルを場所でソートすると、ライブラリのすべての関数を選択するのが容易になります。
空のスタブ ファイルへのユーザー定義スタブの追加
空のスタブ ファイルにユーザー定義スタブを追加するには、次の操作を行います。
- 次のいずれかの方法でスタブ ウィザードを開きます。
- [スタブ] ビューでスタブを作成する関数を右クリックし、[ユーザー スタブを作成] をクリックします。
プロジェクト ツリーでスタブのディレクトリを選択し、
[C++test] メニューの [ウィザード] > [新規ユーザー スタブ ファイルの作成...] をクリックします。ウィザードが開きます。ウィザードの関数テーブルでスタブを作成する関数を選択し、[次へ] をクリックします。
- 空のスタブ ファイルを作成するため、関数テーブルでは関数を選択しません。
- [次へ] をクリックします。
- スタブ ファイルの名前と場所を入力します。
- [終了] をクリックします。 スタブ ファイルが自動的にエディターで開かれます。
- stub とタイプしてスタブのテンプレートを作成し、"stub" の "b" の直後にカーソルを置いて Ctrl+ Space キーを押し、適切なテンプレートを選択します。テンプレートにはC または C++ 関数の標準スタブ テンプレートまたはコンストラクター/デストラクター テンプレートがあります。
- ret_type、scope、name、parameters の箇所に適切な値を挿入します。
- コンストラクター スタブを除く C++test のスタブはオリジナルの関数と同じ値を受け取ることに注意してください。
ヒント
- Tab キーを使用して ret_type、scope、name、parameters の間を移動できます。
- スタブのボディ (定義) を入力します。
- 「ユーザー定義スタブのための C++test API 関数」で説明されているように、ユーザー定義スタブは C++test API 関数とやり取りできます。
- 変更されたファイルを保存します。
プロジェクト外のライブラリのシンボルをスタブ化するには
次の操作を行って、テスト コンフィギュレーションの関数スタブ モードが [プロジェクト外部のシンボルにもスタブを使用する] に設定されていることを確認します。
- [Parasoft] メニューの [テスト コンフィギュレーション] をクリックします。
- スタブを使用したテストを実行するときに使っているテスト コンフィギュレーションを選択します。または新規テスト コンフィギュレーションを作成します。
- [実行] > [全般] タブをクリックします。
- [インストゥルメント モード] ドロップダウン リストから [カスタム インストゥルメント] を選択します。
- [インストゥルメント モード] ドロップダウン リストの右側の [編集] ボタンをクリックします。
- [インストゥルメントの機能] ダイアログ下部の [関数スタブ モード] を [プロジェクト外部のシンボルにもスタブを使用する] に設定します。
仮想関数のスタブ化
仮想関数をスタブ化する場合、ポインターまたは参照がコンパイル時に指すクラスの関数に対して必ずスタブを作成してください。
たとえば次のコードでは、(*) でマークされた呼び出しは、Base::doSth() 関数のスタブが作成される場合にだけスタブ化されます。ポインターによって指し示すオブジェクトの実際の実行時の型は関係ありません。
void example(Base* ptr) { // ... ptr->doSth(); // (*) // ... }
演算子のユーザー定義スタブを作成するには、次のスタブ関数名を使用します。
演算子 | 関数名 |
---|---|
new | CppTest_Stub_operator_new |
delete | CppTest_Stub_operator_delete |
new[] | CppTest_Stub_operator_array_new |
delete[] | CppTest_Stub_operator_array_delete |
+ | CppTest_Stub_operator_plus |
- | CppTest_Stub_operator_minus |
* | CppTest_Stub_operator_star |
/ | CppTest_Stub_operator_divide |
% | CppTest_Stub_operator_remainder |
^ | CppTest_Stub_operator_excl_or |
& | CppTest_Stub_operator_ampersand |
| | CppTest_Stub_operator_or |
~ | CppTest_Stub_operator_or |
! | CppTest_Stub_operator_not |
= | CppTest_Stub_operator_assign |
< | CppTest_Stub_operator_lt |
> | CppTest_Stub_operator_gt |
+= | CppTest_Stub_operator_plus_assign |
-= | CppTest_Stub_operator_minus_assign |
*= | CppTest_Stub_operator_times_assign |
/= | CppTest_Stub_operator_divide_assign |
%= | CppTest_Stub_operator_remainder_assign |
^= | CppTest_Stub_operator_excl_or_assign |
&= | CppTest_Stub_operator_and_assign |
|= | CppTest_Stub_operator_or_assign |
<< | CppTest_Stub_operator_shift_left |
>> | CppTest_Stub_operator_shift_right |
>>= | CppTest_Stub_operator_shift_right_assign |
<<= | CppTest_Stub_operator_shift_left_assign |
== | CppTest_Stub_operator_eq |
!= | CppTest_Stub_operator_ne |
<= | CppTest_Stub_operator_le |
>= | CppTest_Stub_operator_ge |
&& | CppTest_Stub_operator_and_and |
|| | CppTest_Stub_operator_or_or |
++ | CppTest_Stub_operator_plus_plus |
-- | CppTest_Stub_operator_minus_minus |
->* | CppTest_Stub_operator_arrow_star |
-> | CppTest_Stub_operator_arrow |
() | CppTest_Stub_operator_function_call |
[] | CppTest_Stub_operator_subscript |
<? | CppTest_Stub_operator_gnu_min |
>? | CppTest_Stub_operator_gnu_max |
, | CppTest_Stub_operator_comma |
定義のないシンボルのスタブを生成する
定義のないシンボルの自動スタブを生成するには、次の操作を行います。
- [スタブ] ビューのテーブルで関数を右クリックし、ショートカット メニューの [自動スタブを作成] をクリックします。
自動スタブ ファイルが作成され、エディターで開かれます。
ファイルには適切な定義と必要な #include ディレクティブが自動的に追加されます。
注意
自動スタブには以下の特徴があります。
- 複数の関数のスタブを 1 度に作成できます。テーブルで複数の関数を選択し、選択を右クリックして [自動スタブを作成] ショートカット メニューをクリックします。すべての自動スタブが同じスタブ ファイルに追加されます。
- 利用可能な定義がないシンボルに対してだけ作成できます。その他のシンボルに対してはユーザー定義スタブを代わりに使用します。
- 自動スタブの優先度は最低です。他に利用可能な定義がある場合は、自動スタブは使用されません。
自動生成スタブのカスタマイズ
C++test では、見つからない関数定義のためのスタブを自動生成できます。詳細については 「スタブの自動生成とカスタマイズ」を参照してください。
自動生成スタブはユーザー定義スタブと同じ機能を持ちます。ただし、接頭辞は異なります。ユーザー定義スタブの接頭辞は CppTest_Stub_
であり、自動生成スタブの接頭辞は CppTest_Auto_Stub_
です。このため、ユーザーはスコープ中の 1 つの関数に複数のスタブを用意できます。
完全なスタブ定義を自動生成できない場合、C++test はユーザーがカスタマイズできるスタブ テンプレートを作成します。ユーザーは、適切な return 文を入力したり、インクルード ディレクティブを追加したりすることができます。スタブ テンプレートは自動生成後にファイルに保存されます。
自動生成スタブが使用されるのは、他の定義 (ユーザー定義スタブとオリジナル関数) がない場合だけです。
動的スタブ API から、またはテスト ケース エディターのスタブ ステップ を使って、自動生成スタブを簡単に構成することができます (「動的スタブ」 および 「ステップの設定」 を参照)。
まれなケースとして、動的スタブ API やテスト ケース エディターでは不十分な場合、生成されたスタブの本体を、CppTest_IsCurrentTestCase
スタブ関数などのカスタム ロジック実装で完全に置き換えることができます ( 「 ユーザー定義スタブのための C++test API 関数」 を参照)。
スタブまたはスタブ テンプレートをカスタマイズするには、次の操作を行います。
- スタブ ファイルを開きます。スタブ ファイルは、テスト コンフィギュレーションの [実行] > [シンボル] タブの [自動生成スタブ出力先] で設定された場所に保存されています。
- ret_type、スコープ、名前、パラメーターを変更します。
C++test のスタブは、コンストラクター スタブを除き、オリジナル関数と同じ値を取ります。
スタブの本体/定義を入力します。
- ユーザー定義スタブでは C++test API 関数を使用できます。詳細については 「ユーザー定義スタブのための C++test API 関数」を参照してください。
- 変更後のファイルを保存します。
- 解析を再度実行します。
自動生成されたセーフ スタブ定義の無効化
セーフ スタブ定義は、「危険な関数」を置き換えるために自動生成されます。セーフ スタブ定義は、ほとんどのシステム I/O ルーチン (rmdir()
、remove()
、rename()
など) について使用できます。セーフ スタブ定義を使用した場合、たとえオリジナル関数があってもオリジナル関数は呼び出されません。利用できる場合はセーフ スタブ定義を使用することを推奨します。セーフ スタブ定義を使用すると、単体テスト中に発生する問題を防止できます。ただし、セーフ スタブ定義をユーザーが変更することはできません。
自動生成されたセーフ スタブ定義を使用しない場合は、テスト コンフィギュレーションでセーフ スタブ定義を無効化します。[実行] タブの [シンボル] タブの [次の場所で発見されたファイルのシンボルも使用] フィールドから ${cpptest:cfg_dir}/safestubs
エントリを削除します。
特定の関数についてセーフ スタブの使用を無効化してオリジナル定義を使用するには、オリジナル関数の呼び出しのラッパーとして機能するユーザー定義スタブを作成します。
例:
int CppTest_Stub_mkdir(const char* p) { return mkdir(p); }
ユーザー定義スタブのための C++test API 関数
void CppTest_Assert(bool test, const char * message)
この関数は標準の assert 関数と同じように動作します。test パラメーターの値が失敗するたびにテスト ケースの実行が停止されます。その場合、テスト ケースの結果として「ユーザー定義のアサーションが失敗した」という内容のメッセージがレポートされます。さらに、message パラメーターの値、場所、およびスタック トレースの情報が詳細情報として表示されます。
void CppTest_Break()
この関数を使うと、無条件でテスト ケースの実行を停止できます。「ユーザー定義のブレークが呼び出された」という内容のメッセージが表示されるほか、場所とスタック トレース情報が表示されます。
bool CppTest_IsCurrentTestCase(const char* id;
現在実行されているテスト ケースを問い合わせることができます。現在実行されているテスト ケース名に testCaseName が一致する場合、この関数は true を返します。 一致しない場合、false を返します。この機能は、外部関数の呼び出しに基づいた条件文を使用する関数に役立ちます。例については 「テスト ケースから起動されるスタブ」 を参照してください。
bool CPPTEST_DS_HAS_COLUMN(const char* name)
この関数を使用すると、ユーザー定義スタブと自動スタブのデータ ソース列をクエリーできます。データ ソースはテスト ケース固有であるため、特定のテスト ケースの文脈でスタブが呼び出される場合にだけデータを利用できることに注意してください (グローバルな初期化中などにスタブが呼び出された場合、データを利用することはできません) 。
const char* CppTest_GetCurrentTestCaseName(); const char* CppTest_GetCurrentTestSuiteName();
現在実行されているテスト ケース/テスト スイートの名前を取得します。特定のテスト スイートの特定のテスト ケースに適用するスタブを作成できます。
例については 「テスト ケースから起動されるスタブ」 を参照してください。
スタブでのデータ ソースの使用
C++test で使用するために設定した任意のデータ ソースをスタブで使用できます。
データ ソースを設定するには、「データ ソースの追加」 で説明されている操作を行います。
スタブでデータ ソースを使用するには、ブール型の CPPTEST_DS_HAS_COLUMN(const char* name) API 関数を使用します。次のようにしてデータ ソースの列をクエリーできます。
int CppTest_Stub_goo (void) { if (CPPTEST_DS_HAS_COLUMN("stub_goo_return")) { return CPPTEST_DS_GET_INTEGER("stub_goo_return"); } else { return 0; // Data Source not available } }
データ ソースはテスト ケースに固有であり、テスト ケースのコンテキストでスタブが呼び出される場合にだけデータを使用できることに注意してください。グローバルな初期化の最中にスタブが呼び出された場合などには、データは使用できません。
bool CPPTEST_DS_HAS_COLUMN(const char* name)
マクロは、CppTest_isCurrentTestCase() などの他の API 関数と組み合わせて使用できます。
コンテキストごとに異なるテスト/スタブを使用する
「異なるコンテキストでの異なるテスト/スタブの使用」を参照してください。
テスト ケースから起動されるスタブ
C++test では、現在実行されているテスト ケースから起動できるユーザー定義スタブを作成できます。C++test API には次の関数があります。
bool CppTest_IsCurrentTestCase(const char* id);
この関数を「ユーザー スタブ」定義で使用すると、現在実行されているテスト ケースを確認できます。現在実行されているテスト ケースと引数 testCaseName が一致する場合、この関数は true
を返します。一致しない場合は false
を返します。
この関数は、外部関数呼び出しに基づいた条件文を使用する関数に役立ちます。たとえば:
void foo() { if (goo() == 1) { //code } else { //code } }
100% の行カバレッジを得るために、ユーザーは foo()
関数に対して 2 つのテスト ケースを作成し、次に goo()
関数に対して 1 つのユーザー スタブを作成できます。
int ::CppTest_Stub_goo() { if (CppTest_IsCurrentTestCase("TestCase1")) { return 1; } else { return 0; } }
このスタブはテスト ケースによって起動できます。この例では、現在実行されているテスト ケース によって戻り値が変わります。現在実行されているのが TestCase1
の場合、戻り値は 1 であり、それ以外の場合、戻り値は 0 です。この処理によって、foo()
関数のカバレッジを 100% 取得できます。
テスト ケースによるスタブ ドライバーの作成に役立つ API 関数として、 const char* CppTest_GetCurrentTestCaseName();
および const char* CppTest_GetCurrentTestSuiteName();
があります。 これらの API 関数は、現在実行されているテスト ケースとテスト スイートの名前をそれぞれ取得します。これらの API 関数を使用すると、特定のテスト スイートの特定のテスト ケースに適用するスタブを作成できます。たとえば次のスタブは、AllocTestSuite テスト スイートのテスト ケースで名前に nomemoryを含むすべてのテスト ケースについて、異なった振る舞いをします。
#include <string> #include <stdlib.h> EXTERN_C_LINKAGE void* CppTest_Stub_malloc(size_t size) { std::string testSuiteName = CppTest_GetCurrentTestSuiteName(); std::string testCaseName = CppTest_GetCurrentTestCaseName(); if ((testSuiteName == "AllocTestSuite") && (testCaseName.find("nomemory") != std::string::npos)) { // Simulate no memory situation. return 0; } return malloc(size); }
ユーザー定義スタブ ファイルのためのカスタム コンパイラ オプション
ユーザー定義スタブ ファイルごとに、カスタム コンパイラ オプションを設定できます。オプションを設定すると、たとえば C++test 固有のフラグを使用できます。詳細については 「コンパイラとリンカーのオプション設定」を参照してください。