よくある質問
Google C++ Testing Framework に関するヒントとよくある質問
ここを見て疑問が解決できないならば, 入門ガイド や 上級ガイド を読んだり, googletestframework@googlegroups.com にメールを送ったりしてください.
今使っている C++ testing framework の代わりに Google Test を使うべきなのはなぜですか?
まず最初に,どの C++ testing framework が 最高 かを議論するつもりはない,ということを言わせてください.C++ テスト用の多くの優れたフレームワークがありますが,我々は,その開発者やユーザに敬意を払っています.(今も,これからも)ただ1つの最高のフレームワークが存在するとは考えていません.あなたが取り組んでいるタスクにあった適切なツールを選択する必要があります.
我々が Google Test を開発したのは,既存のフレームワークには, 我々の 要求を満たす機能の組み合わせと利便性を兼ね備えたものが見つからなかったからです.Google Test で 我々が 気に入っているところを以下に示します.これらが Google Test だけの特徴だとは言いません.むしろ,これらを全て備えていることが Google Test を選ぶ理由になっています.あなたも Google Test を選ぶかどうか,このリストが判断の役に立つことを願います.
- Google Test はポータブルに設計されています:例外やRTTIを必要としませんし,様々なコンパイラや環境のバグに対応しています.結果として,Linux や Mac OS X,Windows,そしていくつかの組み込みOS でも動作します.
- 致命的でないアサーション(EXPECT_*)を利用すると,1回の「編集-コンパイル-テスト」サイクルにおいて,テストが複数の失敗を報告できるので,大いに時間が節約できます.
- 役立つメッセージを生成するアサーションを簡単に書くことができます:好きな情報を追加するには,例えば,ASSERT_EQ(5, Foo(i)) << ” where i = ” << i; というようにストリーム構文を使うだけです.これには,マクロや特殊な関数を必要としません.
- Google Test は自動的にテストを検出するので,それらを実行順に列挙する必要はありません.
- あなたが望むすべての機能を備えたフレームワークは存在しませんが,Google Test では,EXPECT_PRED* を利用してアサーションの種類を簡単に増やせます.また,EXPECT_PRED* を使って,自分の使いやすいアサーションマクロを定義して,より便利な構文にすることもできます.
- Death テストは,製品版コードのアサーションが正しい条件で動作することを保証するのに非常に役立ちます.
- サブルーチンやループの内側でアサーションが失敗した場合,SCOPED_TRACE を使うと,そのコンテキストを理解する助けになります.
- テスト名のパターンを利用して,どのテストを実行するかを決めることができます.テスト失敗を素早く再現したい場合に,時間が節約できます.
- Google Test は,Hudson のような有名な continuous build システムでパース可能なXML形式のテスト結果レポートを出力できます.
- Google Test を使うと,単純なテストは簡単に行えますし,難しいテストも実現可能です:つまり,グローバルテスト環境や値や型によって並列化されたテストなどの高度な機能に加えて,Google Test はユーザがこのフレームワークを拡張する様々な方法を提供します.既存の Google Test では実現できない事があれば,Google Test 自身には手を加えずに,Google Test の public API を利用して,ユーザがその機能を実装する事も可能かもしれません.ユーザができることは以下の通りです:
* カスタム述語関数を定義して,テスト用の語彙を拡張する
* ユーザ定義型の表示方法を Google Test に教える
* 独自のテストマクロやユーティリティを定義して,Google Test のサービスプロバイダインタフェースを利用してそれらを検証する
* テストイベントを中断することで,テストケースを見直したり,テストの出力フォーマットを変更したりする.
Google Test をコンパイルする際に警告が出ます.直してもらえますか?
我々は,Google Test 生成時の警告を最小限にしようと努力しています.新しいバージョンをリリースする前に,Windows,Linux,Mac OSでの CMake スクリプトを利用して,コンパイル時に警告が出ないことを確認するためにテストを行っています.
しかし残念ながら,これは,ユーザの環境で Google Test をコンパイルした際に警告が出ないことを保障するものではありません:
- ユーザは,我々とは別のコンパイラ,または同じコンパイラの別のバージョンを利用しているかもしれません.すべてのコンパイラに対するテストは到底不可能です.
- ユーザは,我々とは別のプラットフォームでコンパイルしているかもしれません.
- ユーザのプロジェクトで,我々とは別のコンパイラフラグを利用しているもしれません.
すべての人の Google Test で警告を出なくするというのは,常に可能というわけではありません.また,その警告がまれにしか有効でなく,それの修正がコードをより複雑にしてしまうならば,それは意味がないかもしれません.
Google Test のコンパイル時に警告がでた場合,Google Test のヘッダをシステムヘッダとしてマークするために(GCC を利用していると仮定して)-isystem フラグを利用することを勧めます.これは,Google Test ヘッダからの警告を抑制してくれるでしょう.
なぜ,テストケース名やテスト名にアンダースコアを利用してはいけないのでしょうか?
C++ はコンパイラや標準ライブラリで利用するために以下の識別子を予約しており,アンダースコア(_)は特殊な文字と言えます:
- _ の後に大文字で始まる任意の識別子
- 連続したアンダースコア(つまり,__)を名前に含む任意の識別子
ユーザのコードでは,このような識別子を利用することは禁止されています.
さて,これが TEST や TEST_F にどのような影響を与えるのか見てみましょう.
現在, TEST(TestCaseName, TestName) は, TestCaseName_TestName_Test という名前のクラスを生成します.TestCaseName や TestName に _ が含まれていると何が起こるでしょうか?
- TestCaseName が _ の後に大文字で始まると(例えば,_Foo),_Foo_TestName_Test とう名前になってしまい,これは予約されているので無効になります.
- TestCaseName が _ で終わると(例えば,Foo_),Foo__TestName_Test という名前になり,無効になります.
- TestName が _ で始まると(例えば,_Bar),TestCaseName__Bar_Test という名前になり,無効になります.
- TestName が _ で終わると(例えば,Bar_),TestCaseName_Bar__Test という名前になり,無効になります.
つまり,TestCaseName と TestName が,_ で始まったり終わったりできないことは明らかです(実際には,_ の後が大文字でなければ, TestCaseName は _ で始まることができます. しかし,これでは複雑になってしまいますので,簡単のために, _ で始めてはいけない,としています).
TestCaseName と TestName の先頭や末尾ではなく中間にだったら, _ が含まれても良いように思えます.しかし,次の例を考えてみてください:
TEST(Time, Flies_Like_An_Arrow) { ... }
TEST(Time_Flies, Like_An_Arrow) { ... }
この 2つの TEST は,どちらも同じクラス(Time_Files_Like_An_Arrow_Test)を生成します.これは,良くありません.
やはり簡単のため,TestCaseName や TestName に _ を含めないように,とだけお願いしておきます.このルールは必要というよりは制約に近いですが,簡単で覚えやすいものです.また,これによって,将来的に Google Test の実装を変更する必要が出てきた場合も,多少の融通が利くようになります.
このルールを破っても,すぐには影響がないかもしれませんが,新しいコンパイラ(あるいは,今のコンパイラの新しいバージョンで)や Google Test の新しいバージョンでテストが失敗する可能性(あくまでも可能性)があります.よって,ルールに従うのがベストな選択です.
コンパイル済みの Google Test を(例えば /usr/local に)インストールするのが推奨されないのはなぜですか?
開発初期は,*nix システム上で make insall して,コンパイルした Google Test ライブラリをインストールできました.すると,Google Test を際コンパイルしなくても,そのマシンを使うすべてのユーザがテストを書けます.
良いアイディアのように思えますが,これには1つ問題があります:つまり,すべてのユーザが,Google Test のバイナリをコンパイルするのに使ったコンパイラフラグと 同じ フラグを使ってテストをコンパイルする必要があります.そうしなければ,未定義の挙動に出くわす可能性があります(つまり,テストがおかしな動作をしたり,理由もなくクラッシュしたりすることが起こり得ます).
なぜでしょうか?C++ には One-Definition rule と呼ばれるものがあるからです.同じクラス/関数/変数に対する異なる定義を含む2つの C++ ソースファイルがある場合に,これらを一緒にリンクしてしまうとルール違反になります.リンカは,このエラーを検知するかもしれないし,しないかもしれません(多くの場合,標準 C++ ではこの違反の検知が必須というわけではありません).検知されない場合,実行時に,予想外でデバッグ困難な挙動を示すことになります.
Google Test とテストコードを,それぞれ異なるコンパイラフラグでコンパイルすると,(例えば,Google Test では #if を利用しているので)同じクラス/関数/変数に別の定義があるように見える可能性があります. したがって,混乱しないためにも,コンパイル済みの Google Test ライブラリをインストールしないことをお勧めします.代わりに,プロジェクトごとに Google Test 自体をコンパイルして,Google Test とテストのコンパイルに確実に同じフラグが使われるようにしてください.
Windows(Visual Studio 2008) で 64-bit バイナリを作るにはどうすればいいですか?
(Trevor Robinson の回答)
Visual Studio ソリューションファイル msvc\gtest-md.sln または msvc\gtest.sln をロードしてください.変換ウィザードによって,ソリューションファイルとプロジェクトファイルが Visual Studio 2008 向けに変換されます.ビルドメニューの 構成マネージャ... を選択してください.次に,アクティブソリューションプラットフォーム ドロップダウンメニューから,<新規作成...> を選択してください.新しいプラットフォームドロップダウンメニューからの x64 を選択して,設定のコピー元は Win32のままにします.新しいプロジェクトプラットフォームを作成する,にチェックを入れて,OK をクリックします.Win32 と x64 のプラットフォーム構成ができたので,標準の ツールバーから選択でき,32-bit または 64-bit バイナリを切り替えて作成できます(バッチビルドを使って両方いっぺんにビルドすることもできます).
出力ファイルが上書きされるのを防ぐには,すべてのプロジェクトで,新しく作成したプラットフォーム構成の中間ディレクトリ設定を変更する必要があります.これを行うには,ソリューションエクスプローラで,すべてのプロジェクトを(例えば,シフトキーを押しながら)複数選択します.そのうち1つを右クリックして,プロパティ を選択します.左上にある 構成プロパティ の 構成 ドロップダウンメニューから,すべての構成 を選択します.プラットフォームが x64 になっていることを確認してください.中間ディレクトリ 設定を, $(PlatformName)\$(ConfigurationName) から $(OutDir)\$(ProjectName) に変更します.OK をクリックして,ソリューションのビルドを行います.ビルドが完了すると,msvc\x64\Debug ディレクトリに 64-bit バイナリができます.
MinGW で Google Test を利用できますか?
我々自身がテストしたわけではありませんが,Per Abrahamsen の報告によると,Cygwin から MinGW を使って Google Test のコンパイルとインストールに成功したそうです.次のように設定する必要があります:
PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"
-mno-cygwin オプションを,MinGW バイナリへの直接リンクに置き換えることもできるはずですが,我々は試していません.
注意事項:
- コンパイル時に,大量の警告が出ます.
- Google Test 自身に対するテストが,すべて MinGW との互換性があるわけではないので,make check ではエラーがでます.
WxWidgets のサイトにある この方法 を用いて Linux 上で,MinGW 用の Google Test バイナリをクロスコンパイルできたという報告も受けています.
MinGW のサポート強化に興味があれば, googletestframework@googlegroups.com に連絡をお願いします.
Google Test では,EXPECT_NE(NULL, ptr) や ASSERT_NE(NULL, ptr) ではなく,EXPECT_EQ(NULL, ptr) や ASERT_EQ(NULL, ptr) をサポートしているのはなぜですか?
C++ の仕様により,EXPECT_XX() および ASSERT_XX() マクロの引数として NULL をサポートするには,テンプレートメタプログラミングの複雑なテクニックが必要になります.よって,必要な場所だけで,そうするようにしています(そうしなければ,Google Test の実装は,必要以上にメンテナンスし難く,間違いが起こりやすいものになっていたでしょう).
EXPECT_EQ() マクロは,最初の引数として 期待する 値,2番目の引数として 実際の 値をとります.EXPECT_EQ(NULL, some_expression) と書きたいと考える人がいても不思議ではありませんし,実際,何度も要望はありました.なので,我々はこれを実装しました.
EXPECT_NE(NULL, ptr) の必要性は,これほど強くはありません.アサーション失敗時には, ptr が必ず NULL であることが分かっているので,この場合,追加の情報は出力されません.つまり, EXPECT_TRUE(ptr != NULL) マクロの動作で十分だということです.
もし EXPECT_NE(NULL, ptr) をサポートするならば,整合性を保つために EXPECT_NE(ptr, NULL) も同様にサポートしなければいけないでしょう.EXPECT_EQ とは違って,EXPECT_NE の引数の順番には特に決まりがないからです.これはつまり,実装時に使われるテンプレートメタプログラミングの技法が2倍になり,理解やメンテナンスがより困難になる,ということです.これをサポートしてもコストに見合わない,と我々は考えています.
最後に,我々は EXPECT_THAT(value, matcher) という統合構文をテストでもっと使うように勧めています.これは,Google Mock の matcher ライブラリを利用したものです.matcher を利用する大きな利点の1つは,matcher を組み合わせて新しい matcher を簡単に作れる,ということです.一方,EXPECT_NE などのマクロを組み合わせるのは容易ではありません.よって,EXPECT_XX() マクロよりも matcher に注力していきたいと考えています.
Google Test ではテストの並列実行をサポートしていますか?
テストランナーはビルド/テスト環境と密接に関係している傾向があり,これはテストを並列に実行する際に問題になりますが,Google Test はこの問題を無理に解決しようとはしません.代わりに,Google Test をテストランナーと一緒にうまく動作するようにしました.例えば,Google Test の XML レポートには,各テストの実行時間が含まれており,また,テストメソッド実行を複数のプロセスに分けて行うためには, gtest_list_tests や gtest_filter フラグが利用できます. これらの機能は,テストランナーがテストを並列実行するのに役立ちます.
Google Test が,テストをマルチスレッドで実行して高速化しないのはなぜですか?
スレッドセーフなコードを書くのは難しいことです.ほとんどのテストは,スレッドの安全性を考慮して書かれておらず,マルチスレッド環境では正しく動作しません.
考えてみると,他のスレッドが何をしているのか知っている場合でさえ,正しく動くコードを書くのは困難です.他のスレッドが何をしているのか分からずに正しく動くコードを書くのは,それよりもずっと難しいですし,不可能な場合さえあります(あなたがテストを書いた後でも,テストメソッドが追加,削除,変更される可能性があることを考えてください).テストを並列に実行したいならば,マルチプロセスで実行するのがより良い方法でしょう.
Google Test のアサーションが例外を使った実装になっていないのはなぜですか?
我々の元々のモチベーションは,例外が使えないプロジェクトで Google Test を利用できるようにすることでした.その後,このアプローチには他にも利点があることに気付いたのです:
C++では,デストラクタで例外を投げたときの動作が未定義です.例外を使わないことで,Google Test のアサーションはデストラクタでも安全に利用できます.
EXPECT_* マクロは,これが失敗した後でも処理が続行されるので,1回の実行で1つの TEST 中の複数の失敗を報告できます.通常,C++ の「編集-コンパイル-テスト」サイクルは非常に長く,1度で複数の修正ができるようになってきているのはありがたいので,これは人気の機能です.
もしアサーションが例外を用いて実装されていたとしたら,その例外がユーザにキャッチされてしまうと失敗を見逃してしまいます:
try { ... ASSERT_TRUE(...) ... }
catch (...) { ... }
上記のコードは,ASSERT_TRUE が例外を投げた場合でも成功してしまいます.テストでこのように書くことはなさそうですが,テストされるコードから呼ばれるコールバック中にアサーションを書くときには,このようなパターンに出くわす可能性があります.
例外を使用しないことの欠点は,ASSERT_* (return を用いた実装)は,現在の関数を終了させることはできても現在の TEST を終了させることはできない,ということです.
フィクスチャを使う場合と使わない場合とで別のマクロを使うのはなぜですか?
残念ですが,C++ のマクロシステムでは,これらの場合で同じマクロを利用することはできません.フィクスチャを用いるテスト用の1つのマクロだけを提供して,ユーザに空のフィクスチャを定義してもらう,という手段も可能ではあります:
class FooTest : public ::testing::Test {};
TEST_F(FooTest, DoesThis) { ... }
または,
typedef ::testing::Test FooTest;
TEST_F(FooTest, DoesThat) { ... }
しかし,これでは1行コードが多すぎると思われるでしょう.:-) 我々の目的は,テストを楽に書けるようにすることだったので,簡単なテストは簡単に作れるようにしました. これが,それぞれのテスト用にマクロが分かれている理由です.
どちらのアプローチも理想的とは言えなくても,合理的ではあると考えています.結局,おそらくどちらの方法にしても,そこまで重要な問題ではありません.
テストフィクスチャとして構造体を利用しないのはなぜですか?
我々の方針は,受動的なデータを表現するときにだけ構造体を利用する,というものです.このように構造体とクラスを区別すると,コードを書く人間の意図を上手く示すことができます.テストフィクスチャには setUp() や TearDown() などのロジックが含まれているので,これはクラスとして定義されるのが良いでしょう.
Death テストは アサーションとして実装されていますが,代わりにテストランナーを使わないのはなぜですか?
我々の目的は,C++ が許す範囲で,Death テストをユーザにとって便利なものにすることでした.特に,次のような点が挙げられます:
ランナー形式では,情報を2つに分ける必要があります:まず,Death テスト自体の定義.そして,Death テストをどのように実行して,結果として何を期待するか,というランナーの仕様です.Death テストは C++ で書かれるでしょうが,ランナーの仕様は何で書かれているか不明です.ユーザは,これらの協調に気を配る必要があります.ASSERT_DEATH(statement, expected_message) では,必要な情報すべてを,1か所で,かつ1言語で定義します.余計な決まり文句的コードもありません.これは,とても平叙文的です.
ASSERT_DEATH の構文やエラーレポートの挙動は,Google Test のアサーションと似ているので,理解が容易です.
ASSERT_DEATH は,他のアサーションや好きなロジックと一緒に利用することができます.1つのテストメソッドに1つの Death テスト,といった制限はありません.例えば,次のような書き方もできます:
if (FooCondition()) {
ASSERT_DEATH(Bar(), "blah");
} else {
ASSERT_EQ(5, Bar());
}
1つのテストメソッドに1つの Death テストという書き方が好きならば,そのようなスタイルで書くこともできます.しかし,それをユーザに強要することはしたくありません.人為的な制限は,少なければ少ないほど良いです.
ランナーを使った方法は,より静的で柔軟性に欠けたものになりやすく,その分ユーザが努力する必要があります.
ASSERT_DEATH には,もう1つおもしろい点があります. Death テストを実行する子プロセスを作るために fork() を呼ぶ,ということです. fork() は,メモリページのコピーオンライトを利用してほとんどオーバヘッドがないので,これはほぼ瞬間的に動作します. また,子プロセスは,全てのグローバル変数とローカル変数の初期化,その他与えられた文までに存在する全てのコードをスキップして,ユーザの与えた文から直接開始します. もし,子プロセスを一から立ち上げるとすると,テストが多くの動的ライブラリにリンクされている場合,すべてをロードしてテスト開始するまでに数秒の時間がかかるでしょう.
Death テストで状態を変更しても,テスト終了後にはそれが元に戻るようです.なぜですか?
(EXPECT_DEATH などの)Death テストは,サブプロセスで実行されます.ただし, 期待されるクラッシュはテストプログラム(つまり,親プロセス)を殺したりはしません.その結果,メモリ内のあらゆる副作用は,親プロセスではなく,それぞれのサブプロセス内で生じます.テストはどこか別の宇宙で実行されている,と考えてもらっても構いませんよ.
コンパイラが,static const なメンバ変数に対して ”undefined reference” というエラーを出しますが,クラス内でちゃんと定義しています.何がおかしいのでしょうか?
クラスに static データメンバがある場合:
// foo.h
class Foo {
...
static const int kBar = 100;
};
クラス定義の 外 ,foo.cc でもこれを定義する必要があります:
const int Foo::kBar; // ここでは初期化は不要です.
上記のようにしなければ, 無効な C++ のコード になってしまいます.具体的には,Google Test の(EXPECT_EQ などの)比較アサーションを利用したときに,”undefined reference” リンカエラーが起こります.
複数の実装を持つインタフェースがあります.テストセットを1度だけ書いて,すべての実装に対してそれを繰り返し実行することができますか?
Google Test には,まだこの手のテスト,あるいは一般的なデータ駆動テストに対する良い対処法がありません.しかし,すぐにこの部分での改善を行うことができると思っています.
テストフィクスチャが別のテストフィクスチャを継承することはできますか?
できます.
各テストフィクスチャには,それに対応する同じ名前のテストケースがあります.つまり,ある1つのフィクスチャを利用できるのは,1つのテストケースだけだという事です.しかし,場合によっては,複数のテストケースで同じフィクスチャ(あるいは,少しだけ異なったフィクスチャ)を使いたい事があります.例えば, GUI ライブラリのすべてのテストケースが,フォントやブラシなどの重要なシステムリソースをリークしていない事を確認したい場合などがあります.
Google Test では,テストケース間でフィクスチャを共有できます.まず,基底テストフィクスチャで共有ロジックを定義し,その共通ロジックを使いたいフィクスチャを,各テストケース毎に派生させます.そして,それぞれの派生クラスを用いてテストを書くために TEST_F() を利用します.
典型的には,以下の様なコードになります:
// 基底テストフィクスチャクラスを定義します.
class BaseTest : public ::testing::Test {
protected:
...
};
// BaseTest から FooTest フィクスチャを派生させます.
class FooTest : public BaseTest {
protected:
virtual void SetUp() {
BaseTest::SetUp(); // まず,基底フィクスチャクラスの初期化
... additional set-up work ...
}
virtual void TearDown() {
... clean-up work for FooTest ...
BaseTest::TearDown(); // FooTest の終了処理後に,
// 基底フィクスチャクラスの終了処理も忘れずに.
}
... functions and variables for FooTest ...
};
// フィクスチャ FooTest を利用したテスト
TEST_F(FooTest, Bar) { ... }
TEST_F(FooTest, Baz) { ... }
... additional fixtures derived from BaseTest ...
必要ならば,派生したテストフィクスチャからさらに別のフィクスチャを派生させることもできます.Google Test には,この階層の制限はありません.
派生したテストフィクスチャを使う完全な例は,sample5 を参照してください.
コンパイラが,”void value not ignored as it ought to be” というエラーを出します.これはどういう意味ですか?
おそらく,void を返さない関数で ASSERT_*() を使っています.ASSERT_*() を使うことができるのは,void を返す関数の中だけです.
Death テストがハングアップ(または,セグメンテーションフォルト)します.どうやって修正すればよいでしょうか?
Google Test では,Death テストは子プロセスで実行され,その実行方法はデリケートです.Death テストを書くためには,その動作をきちんと理解する必要があります.これを,しっかり読んでください.
特に,Death テストでは,親プロセス内に複数のスレッドを持つのは良くありません.最初に試すことができる方法は,EXPECT_DEATH() の外側でスレッドを作成している部分を削除することです.
不可欠なライブラリが, main() の開始よりも前にスレッドを作る場合などのように,これが不可能な場合もあります.この場合,できる限り多くの処理を EXPECT_DEATH() 内部に移動させる(極端な場合,すべてを内部に移す)か,あるいは逆に,内部の処理をできるだけ少なくするかして,衝突する可能性を最小にします.また,Death テストのスタイルを “threadsafe” に設定することもできます.これは,安全ですが遅くなりますので,使えるかどうか試してください.
スレッドセーフな Death テストを使う場合,子プロセスでテストプログラムが再び最初から実行されることを忘れないでください.つまり,連続的に自分自身を実行し,決定的に動作するプログラムが必要になります.
結局のところ,優れた並列プログラミングが必要だということです.プログラム中で,競合状態やデッドロックが決して起こらないようにしなければいけません.銀の弾丸はないのです - ごめんなさい!
テストフィクスチャのコンストラクタ/デストラクタと,set-up/tear-down 関数のどちらを使うべきでしょうか?
Google Test では,複数のテストで同じテストフィクスチャオブジェクトを再利用したりしない,ということをまず覚えてください.Google Test は,それぞれの TEST_F に対して新しいテストフィクスチャオブジェクトを作成します.そして,SetUp() を すぐに 呼び出し,テストを実行,そして TearDown() を呼び出して,すぐに テストフィクスチャを削除します.したがって,コンストラクタやデストラクタが既にその役割をしているならば,SetUp() や TearDown() 関数を書く必要はありません.
しかし,次のような場合は SetUp()/TearDown() を使いたいと思うかもしれません:
- デストラクタ中で例外が投げられると,未定義の動作がおこり,通常はプログラムが不正終了するので,tear-down 処理が例外を投げる可能性があるならば,デストラクタではなく TearDown() を使うべきです. (STLのような)多くの標準ライブラリは,コンパイラで例外が有効にされた場合には例外を投げます.よって,例外が有効でも無効でも動作するようなポータブルなテストを書きたいならば, TearDown() の方を使うべきでしょう.
- Google Test チームは,例外が有効になっているプラットフォーム(例えば,Windows,Mac OS,そして Linux client-side)では,アサーションマクロが例外を投げるようにすることを検討しています.そうすると,ユーザがサブルーチンで発生した失敗を,呼び出し側まで伝播させる必要がなくなります.したがって,このようなプラットフォームでコードを実行するならば,デストラクタで Google Test のアサーションを使うべきではありません.
- コンストラクタやデストラクタでは,this オブジェクトの仮想関数呼び出しができません.(virtual として宣言されているメソッドを呼び出すことはできますが,それは静的結合されることになります.)したがって,派生クラスでオーバライドされるメソッドを呼び出す必要がある場合は,SetUp()/TearDown() を使う必要があります.
ASSERT_PREDn を使うと,コンパイラが “no matching function to call” というエラーを出します.どうやって修正すればよいでしょうか?
ASSERT_PRED* や EXPECT_PRED* で利用する述語関数がオーバーロードされたものだったり,テンプレートだったりすると,コンパイラは,どのオーバーロードバージョンを使うべきか決めるのが難しくなります.ASSERT_PRED_FORMAT* と EXPECT_PRED_FORMAT* では,この問題は起こりません.
このエラーを見て,分かりやすい失敗メッセージを生成する (ASSERT|EXPECT)_PRED_FORMAT* に変更したいと思うかもしれません.しかし,もしこの方法が選べないならば,コンパイラに利用する関数のバージョンを教えることで,この問題を解決できます.
例えば,次のように定義されているとします.
bool IsPositive(int n) {
return n > 0;
}
bool IsPositive(double x) {
return x > 0;
}
次のように書くと,コンパイルエラーになります.
EXPECT_PRED1(IsPositive, 5);
しかし,次のように書けば問題ありません:
EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
(static_cast 演算子のカギ括弧の中は,IsPositive() の int バージョンを表す関数ポインタの型です.)
また別の例として,テンプレート関数の場合を考えます.
template <typename T>
bool IsNegative(T x) {
return x < 0;
}
述語関数アサーションでは,これを次のように利用します:
ASSERT_PRED1(IsNegative<int>, -5);
テンプレートが2つ以上のパラメータを持つ場合は,より興味深いものになります.次のコードは,コンパイルできません:
ASSERT_PRED2(GreaterThan<int, int>, 5, 0);
C++ プリプロセッサは,ASSERT_PRED2 に,期待より1つ多い4つの引数が与えられたと考えます.回避策は,述語関数を丸括弧で囲むことです:
ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
RUN_ALL_TESTS() を呼ぶと,コンパイラが “ignoring return value” というエラーを出します.なぜでしょうか?
RUN_ALL_TESTS() の戻り値を無視してしまう人が時々います.つまり,
と書く代わりに,
と書く人がいます.これは誤りであり,危険です.テストランナーは,テストが成功したかどうかを決めるために,RUN_ALL_TESTS() の戻り値を知る必要があります.main() 関数がこれを無視すると,Google Test アサーションが失敗した場合でも,テストが成功したと勘違いされてしまいます.これは,よろしくないですね.
ユーザがこの危険なバグにはまらないように,RUN_ALL_TESTS() の戻り値が無視された場合に gcc が警告をだすように実装されています.この警告を見た場合の修正は簡単です.つまり,その戻り値を main() の戻り値として利用するようにしてください.
コンパイラが,コンストラクタ(または,デストラクタ)は値を返せません,というエラーを出します.どうなっているのでしょうか?
ASSERT_* へのストリーミングメッセージの構文,例えば,
ASSERT_EQ(1, Foo()) << "blah blah" << foo;
をサポートするために,コンストラクタとデストラクタで,ASSERT* と FAIL* (EXPECT* と ADD_FAILURE* は大丈夫)を使うことを断念しました.これは,C++ の特性に依存するものです.これの回避策は,コンストラクタ/デストラクタの中身を,private で void を返すメンバ関数に移動するか,あるいは EXPECT_*() が使えるなら,それに切り替えることです.これに関しては,user’s guide の関連セクションで説明されています.
set-up 関数が呼ばれません.なぜですか?
C++ では,大文字と小文字が区別されます.正しい綴りは SetUp() です.Setup() と書いていませんか?
同じように, SetUpTestCase() を SetupTestCase() と書いてしまい,なんで呼ばれないんだ,と悩む人もいます.
Emacs で直接,失敗した行に移動するにはどうすればよいでしょうか?
Google Test の失敗メッセージフォーマットは,Emacs ,そして acme や XCode のような他の多くの IDE でも利用できます. Google Test のメッセージが Emacs のコンパイルバッファに表示されたら,それをクリックすることができます.メッセージを選択してエンターキーを押すとソースコード中の対応する場所に移動し,C-x を押すと次の失敗地点に移動します.
同じテストフィクスチャロジックを共有する,複数のテストケースがあります.毎回,新しいテストフィクスチャクラスを定義する必要がありますか?面倒なのですが.
その必要はありません.
class FooTest : public BaseTest {};
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
class BarTest : public BaseTest {};
TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }
と書く代わりに,テストフィクスチャを typedef すれば良いだけです:
typedef BaseTest FooTest;
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
typedef BaseTest BarTest;
TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }
Google Test の出力が,ログメッセージ全体に埋もれてしまいます.どうすればよいでしょうか?
Google Test の出力は,簡潔で人間が読みやすいレポートになるように作られています.テストがテキスト出力を生成すると,Google Test の出力と混ざって読みにくくなります.しかし,この問題には簡単な解決法があります.
ほとんどのログメッセージは標準エラー出力に送られるので,我々は Google Test 出力を標準出力に出すようにしました.この場合,リダイレクトを利用して2つを簡単に分けることができます. 例を示しましょう:
./my_test > googletest_output.txt
グローバル変数よりもテストフィクスチャの方を使うべきなのはなぜですか?
それには,いくつかの理由があります:
- テストで,グローバル変数の状態を変更する必要がでてくるかもしれません.これによって,あるテストの副作用が別のテストに影響しないようにするのが難しくなり,デバッグが困難になります.フィクスチャを使うと,各テストで新しい(同じ名前の)変数が利用できます.したがって,それぞれのテストの独立性が維持されます.
- グローバル変数は,グローバルな名前空間を汚染します.
- テストフィクスチャは,派生クラスを使って再利用することができますが,グローバル変数ではそれは簡単ではありません.多くのテストケースに共通するものがある場合,これは便利です.
FRIEND_TEST() を使わずに private なクラスメンバをテストするにはどうすればよいでしょうか?
まず,テスト可能なコード,つまり public なインタフェースから簡単にテストできるクラスを書けないか試してみるべきです.このための手段の1つが,Pimplイディオムです:つまり,クラスの private メンバをすべて helper クラスに移動して,helper クラスの全てのメンバを public にします.
FRIEND_TEST を使わずに済む手段は他にもあります:
- テストを,フィクスチャクラスのメンバとして書いてください:
class Foo {
friend class FooTest;
...
};
class FooTest : public ::testing::Test {
protected:
...
void Test1() {...} // これは Foo クラスの private メンバにアクセスできます.
void Test2() {...} // こちらも同様です.
};
TEST_F(FooTest, Test1) {
Test1();
}
TEST_F(FooTest, Test2) {
Test2();
}
- フィクスチャクラスに,テストされるクラスの private メンバのアクセサを書いて,テストではそのアクセサを使ってください:
class Foo {
friend class FooTest;
...
};
class FooTest : public ::testing::Test {
protected:
...
T1 get_private_member1(Foo* obj) {
return obj->private_member1_;
}
};
TEST_F(FooTest, Test1) {
...
get_private_member1(x)
...
}
- メソッドが protected として宣言されているならば,テスト用サブクラスでアクセスレベルを変更できます:
class YourClass {
...
protected: // テストしやすいように protected
int DoSomethingReturningInt();
...
};
// your_class_test.cc ファイルに書きます.
class TestableYourClass : public YourClass {
...
public: using YourClass::DoSomethingReturningInt; // アクセス権を変更
...
};
TEST_F(YourClassTest, DoSomethingTest) {
TestableYourClass obj;
assertEquals(expected_value, obj.DoSomethingReturningInt());
}
FRIEND_TEST() を使わずに private で static なクラスメンバをテストするにはどうすればよいでしょうか?
private な static メソッドがヘッダファイルに散乱しているのを見かけます.それは,実装部分であり,理想を言えば .h ファイルの外部で定義されるべきです.それらをクラスに属さない関数に変更するのは,よくやられる方法です.
例えば,
// foo.h
class Foo {
...
private:
static bool Func(int n);
};
// foo.cc
bool Foo::Func(int n) { ... }
// foo_test.cc
EXPECT_TRUE(Foo::Func(12345));
と書く代わりに,次のように書くと良いでしょう:
// foo.h
class Foo {
...
};
// foo.cc
namespace internal {
bool Func(int n) { ... }
}
// foo_test.cc
namespace internal {
bool Func(int n);
}
EXPECT_TRUE(internal::Func(12345));
異なるパラメータを与えてテストを複数回実行したいのですが,同じことを何度も書く必要がありますか?
いいえ. 値をパラメータ化したテスト と呼ばれる機能を使うことができます.これによって,改めてテストを定義しなくても,異なるパラメータを与えてテストを繰り返すことが可能になります.
main() が定義されているソースファイルをテストするにはどうすればよいでしょうか?
foo.cc ファイルをテストするには,それをコンパイルして,ユニットテストプログラムにリンクする必要があります.しかし,ファイル内で main() 関数が定義されていると,ユニットテストは main() でクラッシュし,その結果ビルドエラーになります.
正しい解決法は,3つのファイルに分割することです:
- 宣言が書かれた foo.h.
- main() 以外の定義が書かれた foo.cc.
- main() の定義だけが書かれた foo_main.cc
foo.cc は,簡単にテストできます.
既存のファイルにテストを追加している途中で,このような煩わしい変更をしたくないならば別の方法もあります:つまり単に,ユニットテストに foo.cc ファイル全体をインクルードするという方法です.以下に例を示します:
// foo_unittest.cc ファイル
// ヘッダファイル
...
// ユニットテストに main() があるので,foo.cc の main() の名前を変更します.
#define main FooMain
#include "a/b/foo.cc"
// ここから,テストを書きます.
...
ただし,これはあくまでもハックであり,最後の手段として使うべきものであることを忘れないでください.
ASSERT_DEATH() の statement 引数には何を与えられますか?
ASSERT_DEATH(_statement_, _regex_)(または,任意の Death アサーションマクロ)は,_statement_ が有効な場所ならどこでも利用できます.通常,_statement_ には,現在のコンテキストで意味が通る任意の C++ の文が利用できます.具体的には,グローバル変数,ローカル変数を自由に参照できる,次のような文が利用可能です:
- 関数の単純な呼び出し(よくあるケース)
- 複雑な式
- 複合文
以下にいくつかの例を示します:
// Death テストでは,単純な関数呼び出しが使えます.
TEST(MyDeathTest, FunctionCall) {
ASSERT_DEATH(Xyz(5), "Xyz failed");
}
// また,変数と関数を参照する複雑な式も使えます.
TEST(MyDeathTest, ComplexExpression) {
const bool c = Condition();
ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
"(Func1|Method) failed");
}
// Death アサーションは,関数のどこでも利用できます.
// ループ内部でも利用できます.
TEST(MyDeathTest, InsideLoop) {
// Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
for (int i = 0; i < 5; i++) {
EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
::testing::Message() << "where i is " << i);
}
}
// Death テストでは,複合文を使うこともできます.
TEST(MyDeathTest, CompoundStatement) {
// Bar(0), Bar(1), ..., Bar(4) の少なくとも1つが
// クラッシュすることを確認します.
ASSERT_DEATH({
for (int i = 0; i < 5; i++) {
Bar(i);
}
},
"Bar has \\d+ errors");}
もし興味があれば,googletest_unittest.cc により多くのサンプルが含まれています.
ASSERT_DEATH で利用される正規表現の構文はどのようになっていますか?
POSIX システム上の Google Test では, POSIX 拡張正規表現構文 を利用します.詳細は, 正規表現の構文 の項を参照してください.
フィクスチャクラス Foo は定義されているのですが,TEST_F(Foo, Bar) で “no matching function for call to Foo::Foo()” というエラーが出ます.なぜですか?
Google Test が,テストフィクスチャクラスのオブジェクトを作れなければならないので,必ずデフォルトコンストラクタが必要です.通常,コンパイラはそれを1つ自動的に定義します.しかし,自分自身で定義しなければならない場合があります:
- Foo クラスのデフォルトではないコンストラクタを明示的に宣言している場合,中身が空でも良いので,デフォルトコンストラクタを定義する必要があります.
- Foo に,const かつ static ではないデータメンバが含まれる場合,デフォルトコンストラクタを定義して,なおかつ, そのコンストラクタの初期化リストで const メンバを初期化する必要があります.(gcc の初期バージョンでは,const メンバの初期化は必須ではありません.このバグは gcc 4 で修正されています.)
既に join されている以前のスレッドについて,ASSERT_DEATH がエラーを出すのはなぜですか?
Linux pthread ライブラリを利用した場合,1度シングルスレッドからマルチスレッドになると,それを戻す方法はありません.初めてスレッドを作成するときに,追加で管理スレッドが作られます.つまり,2スレッドではなく,3スレッドになります.作成したスレッドがメインスレッドに join するとき,スレッドカウントが1つ減りますが,管理スレッドが殺されることはありませんので,2スレッドが動作していることになります.つまり,Death テストを安全に実行することができない,ということです.
新しい NPTL スレッドライブラリは管理スレッドを作成しないので,この問題で悩むことはありません.しかし,どのマシンでテストを実行するかを制御しない場合は,この方法に頼ることはできません.
Google Test で ASSERT_DEATH を利用する場合,FOODeathTest という名前にするために,個々のテスト名ではなくテストケース名が必要になりますが,これはなぜですか?
Google Test は,異なるテストケースのテストを混ぜることはしません.つまり,まず1つのテストケースの全テストが実行され,さらに次のテストケースの全テストが実行され,と続いていきます.Google Test がこのように動作する理由は,テストケース内の最初のテストが実行されるよりも前にテストケースを初期化し,最後に終了処理をする必要があるからです.テストケースを分割すると,初期化と終了の処理が複数必要になり,非効率的で動作も複雑になります.
もし,テストケース名ではなくテスト名に基づいてテストの順序を決めていたら,次のような状況で問題になっていたでしょう:
TEST_F(FooTest, AbcDeathTest) { ... }
TEST_F(FooTest, Uvw) { ... }
TEST_F(BarTest, DefDeathTest) { ... }
TEST_F(BarTest, Xyz) { ... }
FooTest.AbcDeathTest は BarTest.Xyz よりも前に実行する必要があり,異なるテストケースのテストを混ぜないとなると,BarTest テストケースのどのテストよりも前に,FooTest テストケースの全てのテストを実行する必要があります.しかしこれは,FooTest.Uvw よりも前に BarTest.DefDeathTest を実行するという要件に矛盾します.
Death テストと通常のテストの両方を含むテストケースを,FOODeathTest という名前にするのが気に入りません. どうすればよいでしょうか?
とくに必要があるわけではないのですが,もし望むならば,テストケースを FooTest と FooDeathTest に分割して,名が体を表すようにもできます:
class FooTest : public ::testing::Test { ... };
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
typedef FooTest FooDeathTest;
TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
アサーションを使うと,コンパイラが “no match for ‘operator<<’” というエラーを出します.どういうことでしょうか?
アサーションでユーザ定義型 FooType を利用する場合は,FooType の値を出力するための std::ostream& operator<<(std::ostream&, const FooType&) 関数が定義されていることを確認してください.
さらに,ある名前空間内で FooType が宣言されている場合,この << 演算子も,同じ 名前空間で定義される必要があります.
Windows でメモリリークのメッセージを表示させないようにするにはどうすればよいでしょうか?
静的に初期化される Google Test シングルトンは,ヒープ上に配置される必要があるので,プログラム実行終了時に,Visual C++ メモリリーク検出器がメモリリークを報告します.これを避ける最も簡単な方法は,_CrtMemCheckpoint と _CrtMemDumpAllObjectsSince を呼んで,静的に初期化されたヒープオブジェクトを無視することです.詳細やヒープチェック/デバッグの方法については,MSDN を参照してください.
Google Test を使ったプロジェクトを Visual Studio でビルドしていますが,大量のリンカエラー(または警告)が出ます.助けてください!
テストプロジェクトと Google Test が同じコンパイラフラグでコンパイルされていない場合に,そのプロジェクトを Google Test ライブラリにリンクしようとすると,次のようなリンカエラーや警告が大量にでる可能性があります.
- LNK2005: symbol already defined in object
- LNK4217: locally defined symbol ‘symbol’ imported in function ‘function’
- LNK4049: locally defined symbol ‘symbol’ imported
Google Test プロジェクト(gtest.vcproj)では,ランタイムライブラリオプションが /MT(マルチスレッドスタティクライブラリを利用,/MTd はデバッグ用)にセットされています.あなたのプロジェクトが,何か別のオプション,例えば /MD(マルチスレッドDLLを利用,/MDdはデバッグ用)を使う場合,Google Test プロジェクトの設定もそれに合わせて変更する必要があります.
この設定を更新するためには,Visual Studio IDE でプロジェクトのプロパティを開いて,構成プロパティ|C/C++|コード生成 のオプション “ランタイムライブラリ” のオプションを変更してください.また,gtest.vcproj の代わりに gtest-md.vcproj を利用してみるのもよいでしょう.
Solaris で Google Test を使おうとすると,std::type_traits に関するコンパイルエラーが出ます.
Google Test は,SunStudio がサポートしていない標準 C++ ライブラリを一部利用しています.代替となる実装を利用して動作を成功させた報告がありました.以下のコマンドを実行した後にビルドしてみてください:
export CC=cc CXX=CC CXXFLAGS='-library=stlport4'
自分のコードがテスト内で実行されているかどうかを検出するにはどうすればいいでしょうか?
テスト内で実行されているかどうかを検出し,それに応じて挙動を変えるコードを書くと,テスト用ロジックが製品に混入してしまいます.テスト用コードが製品でうっかり実行されない事を確実にするのは,容易ではありません.また,このような愚かな行為は,不確定性バグを生み出すことにもつながります.したがって,このような行為をしないように強く勧めますし,Google Test には,そのような機能は用意されていません.
一般的に,テスト時に異なる動作をさせるたに推奨される方法は,依存性の注入です.テストや製品コードからの異なる機能を注入することができます.製品コードは,テスト用ロジックには全くリンクされないので,それが実際に実行される危険はありません.
しかし,全く,ほんとうに,どうしても他に選択肢がないならば,そして,テストプログラム名を _test で終わるものにするというルールを守るならば,そのコードがテストかどうかを知るために実行プログラム名を検出する(main() の argv[0])という酷いハックもあります.
Google Test で,他のライブラリと衝突するマクロが定義されています.どうすれば良いでしょうか.
C++ では,マクロは名前空間に従いません.したがって,同じ名前のマクロを定義する2つのライブラリは,両方の定義を #include すると衝突します.Google Test マクロが他のライブラリと衝突する場合, Google Test のマクロを強制的にリネームして衝突を回避することができます.
特に,Google Test と別のコードが共にマクロ FOO を定義している場合,コンパイラフラグに
-DGTEST_DONT_DEFINE_FOO=1
を追加して,Google Test にマクロ名を FOO から GTEST_FOO に変えさせることができます.例えば,-DGTEST_DONT_DEFINE_TEST=1 とした場合,テストを定義するには,
TEST(SomeTest, DoesThis) { ... }
の代わりに,
GTEST_TEST(SomeTest, DoesThis) { ... }
と書く必要があります.
正確には,TEST,FAIL,SUCCEED および基本的な比較アサーションマクロは,別の名前を持つことができます.対象となるマクロの完全な一覧は ここ で見ることができます.また,より詳細な情報は,README ファイルの “Avoiding Macro Name Clashes” セクションで述べられています.
知りたいことが,この FAQ に載ってないのですが.
もし,疑問の答えがこの FAQ に載っていない場合でも,他にも利用できるリソースがあります:
- 他の ページ を読んでください
- メーリングリストの アーカイブ を探してください
- googletestframework@googlegroups.com で質問すると,誰かが答えてくれるかもしれません(スパム防止のため,投稿前に ディスカッショングループ に参加する必要があります).
issue tracker は,ごく少数の人間がたまに見ているだけなので,質問に答えてもらうために,ここに issue を作成するのは良い方法ではありません.
質問するときは,以下の情報をできるだけ多く提示することが役に立ちます(質問に関する情報が十分でなければ,手助けできません):
- 利用している Google Test のバージョン(SVN から直接チェックアウトしているならば,リビジョン番号.Google Test は開発中なので,最新バージョンで問題が解決されている可能性もあります)
- 使っている OS
- コンパイラの名前とバージョン
- コンパイル時のコマンドラインフラグすべて
- (質問がコンパイルに関することならば,)コンパイルエラーメッセージすべて
- 問題を起こす実際のコード(理想的には,最小限かつ動作可能なプログラム)