Visual StudioでGoogleTestライブラリを使って、C++の単体テストを回す方法を紹介します。
基本的にはMSドキュメントの通りですが、実用レベルとなると情報が足りていないと思い、記事にすることにしました。
vcpkgを使用している方は以下の記事を参照してください。
1本テストを通す手順
GoogleTestのインストール
Visual Studio Installerから「C++によるデスクトップ開発>Test Adapter for Google Test」にチェックを付けることでインストールできます。
GoogleTestプロジェクトを追加する
プロジェクト追加画面でGoogle Testプロジェクトを追加
構成選択画面が出ますが、基本的にそのままで大丈夫です。
テストするプロジェクトを選択しておくと、依存関係が設定され、ビルド時に、対象のプロジェクトも一緒にビルドされるので少し便利です。
テスト対象のクラスを用意
MyClassというヘッダーとcppファイルを追加して、これをテストしていきます。
構成は以下画像の通りです。
MyClass.h
#pragma once
class MyClass
{
public:
int add(int a, int b);
};
MyClass.cpp
#include "MyClass.h"
int MyClass::add(int a, int b) {
return a + b;
}
テストコードの作成(1回目)
単純に以下のようにテストコードを作成しても、ビルド時に未解決の外部シンボルというエラーが発生します。
これはリンカーの設定が足りていないため、includeしたヘッダーファイルにリンクされるcppファイルが見つかっていない状態です。エラーを解消するにはテストプロジェクトにリンカーの設定を施します。
リンカーの設定
リンクさせなければいけないのはMyClass.objファイルです。
これはビルド時に出力先フォルダに出力されています。
テストプロジェクトにこのファイルを参照させます。
「構成プロパティ>リンカー>入力>追加の依存ファイル」に「../Main/x64/Debug/MyClass.obj;」を追加します。
この状態でビルドすると成功することが確認できます。
テストの実行
リボンメニューからテストエクスプローラーを開きます。
テストエクスプローラーを開いた状態だと、プロジェクトやファイルを右クリックしたときにテスト実行が選択できるようになります。
実行して成功したことが確認できました。
手順の簡略化
テスト自体はこれで可能になりましたが、毎回この手順を行うのは、とても煩わしいと思います。
追加の依存ファイルの設定欄では「*.obj」などワイルドカードを使うこともできないため、MyClass以外のファイルを追加した際にやる必要があります。(MSドキュメントではここまでしか紹介されていませんが。。)
そのため今回はプロジェクトのビルド時に自動で「.obj」ファイルを「.lib」ファイルにまとめて、テストプロジェクト側から参照している位置に配置するようにします。
.objファイルを.libファイルにまとめる
テスト対象のプロジェクトのプロパティを修正する。
「構成プロパティ>ビルドイベント>ビルド後のイベント>コマンドライン」に以下の内容を追加。
lib /NOLOGO /OUT:"$(IntDirFullPath)$(AssemblyName).lib" "$(IntDirFullPath)*.obj"
これでビルド時にlibファイルができあがるようになりました。
.libファイルを参照する
テストプロジェクトの依存ファイルを修正します。
先ほどMyClass.objと指定した箇所を、Main.libに変更します。
ビルドが通ることが確認できます。
別のファイルも追加してみる
試しにMyClass2というファイルを追加してみます。
MyClass2.h
#pragma once
class MyClass2
{
public:
int sub(int a, int b);
};
MyClass2.cpp
#include "MyClass2.h"
int MyClass2::sub(int a, int b) {
return a + b;
}
テストプロジェクトでMyClass2を参照してビルドしてみましたが、無事ビルドもテストも成功しました。
Mockを使うためにgmockの導入
C++のテストを書く際にMockを使いたい場合が多いと思います。
Google製のMockライブラリである「gmock」をVisual Studioに導入していく手順です。
gmockのインストール
Nugetでgmockを検索して、テストプロジェクトにインストールします。
gmock動かすための設定
プリコンパイルヘッダーの設定が「使用する」になっていると、gmockのビルドに失敗してしまうので「使用しない」に変更します。
Mockの動作を確認
Mockの機能が使用できるか確認してみます。
以下のようなテストコードを書いてみました。
#include <gmock/gmock.h>
using ::testing::Return;
// モック化するための抽象クラス
class IMyClass2
{
virtual int sub(int a, int b) = 0;
};
// モックの定義
class MyClass2Mock : public IMyClass2 {
public:
MOCK_METHOD(int, sub, (int a, int b));
};
TEST(TestCaseName, TestName) {
MyClass2Mock myClass2;
// モックの挙動を決定
EXPECT_CALL(myClass2, sub, (1, 1))
.WillOnce(Return(0));
auto result = myClass2.sub(1, 1);
EXPECT_EQ(result, 0);
}
テストを実行してみると無事通ることが確認できました。
gmockの具体的な使い方が知りたい場合は、公式ドキュメントが充実しているためとてもお勧めです。
おわり!