Visual Studio 2022のC++を対象に、ユニットテストとカバレッジ計測を実施する無料環境を構築します。
はじめに
Visual Studio C++で実行するにあたり、ツールを下記基準で選定しました。
- ユニットテストは、Windows以外でも流用可能な知識として、Google Testを採用する。
- Visual Studioのカバレッジ機能はEnterprise版搭載なので、C++が集計できるツールとして、OpenCppCoverageを採用する。
Google Test/Mock
Visual Studio 2022をインストールし、テスト対象となるC++のプロジェクト(Ex. SampleCppソリューション)は作成済みであるとします。
セットアップ
Visual Studioのウィザードで作成したテストプロジェクトおよびNuGetから取得できるGoogle Testはバージョンが古いため、GitHubからCloneしてビルドすることにします(特にGoogle Mock、Old-Style MOCK_METHODn Macros)。
ただし、x64版のプロジェクトのみ登録されているようなので、x86版は自分でプロジェクトを作成する必要があり、あとで説明します。
- スタートメニューから”Developer Command Prompt for VS 2022”プロンプトを起動し、テスト対象のslnフォルダをカレントディレクトリに変更します。
- 下記コマンドを実行します。
> mkdir Tests && cd Tests - 下記コマンドでGoogle Testコードを取得します。
> git clone https://github.com/google/googletest.git
保存場所は任意ですが、今回は$(SolutionDir)Tests\googletestフォルダに格納しました。 - 下記コマンドを実行し、作業フォルダをbuildフォルダに変更します。
> cd googletest
> mkdir build && cd build - 下記コマンドを実行し、Visual Studio版Google Testモジュールをビルドするためのプロジェクトファイルを作成します。
> cmake .. -DBUILD_GTEST=ON -DBUILD_GMOCK=ON -G “Visual Studio 17 2022” - 下記コマンドを実行し、Google TestおよびMockのライブラリモジュールをビルドします。
> msbuild.exe ALL_BUILD.vcxproj /t:Clean;Build /p:Configuration=Release
> msbuild.exe ALL_BUILD.vcxproj /t:Clean;Build /p:Configuration=Debug - ビルドが成功すると、googletest\build\lib内にrelease版およびDebug版のモジュールがフォルダ別に格納されます。
テストプロジェクト作成
ユニットテストコードを記述するプロジェクトを作成します。
- [ソリューションエクスプローラー]を右クリックし、[追加]-[新しいプロジェクト]から”Google Test”を選択します。
- プロジェクト名:任意(テスト対象がわかるもの、今回はSample-Test1としました)
- 場所:任意(今回は、$(SolutionDir)\Testsにしました)
- テストするプロジェクトの選択:テスト対象プロジェクトを選択
- Google Testの使用法:スタティックリンクライブラリ(.lib)
- C++ランタイムライブラリ:動的リンク(推奨)
- ソリューションエクスプローラーからテストプロジェクトSample-Test1の”参照”を右クリックし、”NuGetパッケージの管理”をクリックします。”インストール済み”欄に”Microsoft Google Test…”があるので、アンインストールします。
- x86版が不要な場合は、トップメニュー[ビルド]-[構成マネージャ]をクリックします。Sample-Test1プロジェクト行の[プラットフォーム]-[編集]をクリックして、“Win32″を削除します。
- Debug版の[プロジェクト]-[プロパティ]を開き、以下を設定します。
- [構成プロパティ]-[C/C++]-[全般]-[追加のインクルードディレクトリ]に下記追加。
- $(SolutionDir)Tests\googletest\googletest\include
- $(SolutionDir)Tests\googletest\googlemock\include
- $(SolutionDir)SampleCpp
- [構成プロパティ]-[C/C++]-[コード生成]-[ランタイムライブラリ]を下記に変更。
- マルチスレッドデバッグ(/MTd) ←DLLではない
- [構成プロパティ]-[リンカー]-[全般]-[追加のライブラリディレクトリ]に下記追加。
- $(SolutionDir)Tests\googletest\build\lib\Debug
- [構成プロパティ]-[C/C++]-[全般]-[追加のインクルードディレクトリ]に下記追加。
- Release版プロジェクトにも、上記を参考にRelease用に読み替えて設定します。
- test.cppに以下のinclude, pragmaを加えて、ビルドが成功することを確認します。
#include "pch.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#pragma comment(lib,"gmock.lib")
#pragma comment(lib,"gmock_main.lib")
TEST(TestCaseName, TestName) {
EXPECT_EQ(1, 1);
EXPECT_TRUE(true);
}
テスト実行
製品コードであるSampleCppプロジェクトには、以下のコードを用意しました。
#pragma once
class Calc
{
public:
Calc() {};
virtual ~Calc() = default;
int add(int a, int b);
int sub(int a, int b);
int superSub(int a, int b);
};
#include "Calc.h"
int Calc::add(int a, int b)
{
return a + b;
}
int Calc::sub(int a, int b)
{
return a - b;
}
int Calc::superSub(int a, int b)
{
if (a > 10) {
return b - a;
}
else {
return a - b;
}
}
ユニットテストコードとなるSample-Test1プロジェクトのtest.cppには、以下を記述しました。
テスト対象コードのhとcppファイルをincludeしておくと、トラブルに合うことが少なく効率的です。main関数を含むファイルはここに含めないようにしましょう。
#include "pch.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#pragma comment(lib,"gmock.lib")
#pragma comment(lib,"gmock_main.lib")
#include "calc.h"
#include "calc.cpp"
TEST(Calc, add) {
Calc c;
EXPECT_EQ(2, c.add(1,1));
}
TEST(Calc, sub) {
Calc c;
EXPECT_EQ(1, c.sub(2, 1));
}
TEST(Calc, superSub) {
Calc c;
EXPECT_EQ(1, c.superSub(2, 1));
}
[テスト]-[テストエクスプローラ]から実行することで、テスト結果を確認することができます。
x86版プロジェクト作成
google test/mockのx86版モジュールを作成するには、以下の手順を実行します。
- googletest-distribution.slnをVisual Studioで開きます。
- [ビルド]-[構成マネージャー]をクリックします。
- アクティブソリューションプラットフォームの”新規作成”をクリックします。
- x64をコピー元にして、新規にWin32を作成します。
- 作成後、もう一度アクティブソリューションプラットフォームの編集を開くと”x86″も作成されていると思いますので、”Win32“を削除します。
- 構成マネージャーの一覧で、アクティブソリューションプラットフォームx86のDebug/Releaseに対し、以下のプロジェクトのビルドチェックが外れていることを確認します。
- INSTALL
- RUN_TESTS
- 次に、ソリューションエクスプローラーで、下記プロジェクトをCTRLキーを押しながらクリックし、複数選択した状態で右クリック、”プロパティ”を押下します。
- gmock
- gmock_main
- gtest
- gtest_main
- プラットフォームがWin32であることを確認し、Debug/Releaseに対して、以下の設定を行います。
- [構成プロパティ]-[全般]-[出力ディレクトリ]
$(SolutionDir)$(Platform)\$(Configuration)\ - [構成プロパティ]-[全般]-[中間ディレクトリ]
$(Platform)\$(Configuration)\ - [構成プロパティ]-[ライブラリアン]-[すべてのオプション]-[その他のオプション]
%(AdditionalOptions) /machine:x86
- [構成プロパティ]-[全般]-[出力ディレクトリ]
- Debug/Release版に対しビルドすると、$(SolutionDir)\Win32フォルダ配下にlibが生成されます。
OpenCppCoverage
OpenCppCoverageはGPLv3ライセンスのカバレッジ計測ツールです。C0のみかな。
セットアップ
プラグイン版はVisual Studio 2022に未対応なので、コマンドライン版を使用します。
セットアップはEXEをダウンロードして、実行するだけです。
集計
一番簡単な使い方は、下記です。カレントフォルダにレポートが作成されます。
> OpenCppCoverage.exe --sources={ソースコードフォルダ} -- {実行ファイルパス}
今回の場合、製品コードフォルダとユニットテストEXEを指定すると以下の様になります。計測はDebug版で行います(Release versus Debug)。
※テストプロジェクトのRelease版で、コンパイル設定を最適化無効にするのでもいいかも。
> OpenCppCoverage.exe --sources=SampleCpp -- x64\Debug\Sample-Test1.exe
出力されたレポートは以下の様になります。superSub関数の分岐を通過していないことが分かります。
複数のテストモジュール結果をマージしたい場合、下記の様なやり方ができます。
> OpenCppCoverage --sources=MySources --export_type=binary:Test1.cov -- Test1.exe
> OpenCppCoverage --sources=MySources --export_type=binary:Test2.cov -- Test2.exe
> OpenCppCoverage.exe --sources=MySources --input_coverage=Test1.cov --input_coverage=Test2.cov -- Test3.exe
また、Jenkinsと連携したい場合は、下記の様な出力をさせることも可能です。XXXCoverage.xml(XXXはテストプログラム名)が出力されます。コンディションカバレッジは未サポートです。
> OpenCppCoverage --sources=MySources --export_type=cobertura -- Test1.exe
まとめ
今回は、Windows上でのユニットテスト環境構築方法について紹介しました。
テストを効率化して、質の良いコードを作っていきましょう。
次回は、Google Testの使い方を簡単に紹介する予定です。
以上、Visual Studio 2022でC++の無料Unit Test環境を構築する、でした。
コメント