Google Test + Google MockでのC++単体テスト

gtest-185x160

Google Test + Google Mockでのテスト

GoogleTestの使い方

簡単な使い方はGoogleのドキュメントを読めばなんとかなったので省略。
今回のやり方で困ったところやその解決方法を紹介する

導入

https://github.com/google/googletest
からcloneしてきて、自分のターゲット用にビルド。
Windowsターゲットだったのでmsvcディレクトリの中にあるslnを開き、
[プロパティ]->[C++]->[コード生成]やアーキテクチャを設定するいつもの儀式を行った後にビルド

GoogleTestのほうは
Release : gtest_main.lib / gtest.lib
Debug : gtest_maind.lib / gtestd.lib
となっているのに対し、なぜかGoogleMockはDebug用もRelease用も同一ファイル名で出力される罠があるので
ディレクトリを掘るかリネームして使う必要がある

実装

Dllのテスト

今回はテスト対象がDllだったため、そのままプロジェクトに入れることができなかった。
仕方ないので同一ソリューションにコンソールexeな別プロジェクトを作成、そちらに単体テストを実装する方針となった
最初はcppファイルをincludeする書き方をしていたが、あまりにもアレなのでやめた

また、dllにMockをinjectしたりする方法がわかんなかった(あるのかもわからなかった)ので、
テスト対象のソースを全てテストexeのプロジェクトに追加してテストを行った

Mock

Mock自体の作成はMOCK_METHODヘルパマクロを使えば簡単に作成可能だったが、
このMockをテスト対象のクラスに埋め込む方法で若干困った。
MockしたいクラスがSingletonだったのもあり、最終的にProxyで回避した

サンプル用にシンプルに手抜きされてるがこんな感じにして、TestクラスのSetUp()でcreateInstance自体を書き換えた


class Dependence { public: static std::shared_ptr getInstance() { if ( me_ == nullptr ) me_ = createInstance(); return me_; } static std::shared_ptr me_; static std::function<std::shared_ptr(void)> createInstance; }

非同期Callback関数のテスト

非同期だとローカル変数等がスコープアウトして死んでしまうため、テスト途中でアクセスバイオレーションが出る。
仕方ないのでWindowsAPIで同期待ちを行い回避したが、もっといいやり方がある気がしてならない

TEST_F(SampleTest, Sample) {
auto hEvent = CreateEvent(NULL, TRUE, FALSE, "TestEvent");

target_->asyncFunction( [&](auto& err) {
if ( err != nullptr ) {
FAIL() << "エラーが出たぞ : " << err->getMessage();
SetEvent(hEvent);
} else {
SUCCEED();
}
});

if (WaitForSingleObject(hEvent, TIMEOUT) == WAIT_TIMEOUT) {
FAIL() << "タイムアウト";
}

CloseHandle(hEvent);
}

Jenkins連携

出力されたexeに–gtest_output=xmlをつければJenkinsさんが読めるJUnit形式?のxmlが出るらしい

カバレッジ

どうも取れないもよう。別ツールも探してみたけどあまりいいのがなかった…

##まとめ
ざっとドキュメントを眺めるだけでかなり簡単に導入・利用できたのでおすすめ。