Visual Studio 2022でC++のTDD環境を構築しよう！

# Visual Studio 2022でC++のTDD環境を構築しよう！

ということで、技術選定を兼ねて、C++のTDD環境を構築してみましょう。
今回はWindowsをターゲットとしたC++開発を条件とします。
どのようなビルドシステム x テストフレームワークの組み合わせができるのでしょうか。

## 前提条件

- Visual Studio Community 2022

選定の条件ですが、以下の2つを将来のCI化のために必要条件とします。

- コマンドラインでテストが実行できる
- コマンドラインでビルドが実行できる

また、好ましい要素として以下を挙げておきます。

- テストの追加が難しくないこと
- ターゲットの追加が難しくないこと
- コンパイラの変更(cl.exe->clang++など)ができる
- Git管理と相性が良い
- 開発環境の構築に手間がかからない

## ビルドシステム

- IDE[^1]
- CMake[^1]
- MSBuild[^1]
- Makefile : そのうち・・・
- Bazel : そのうち・・・

[^1]: [Visual Studio でのコンパイルとビルド](https://learn.microsoft.com/ja-jp/visualstudio/ide/compiling-and-building-in-visual-studio?view=vs-2022)

## テストフレームワーク
Microsoft 単体テスト フレームワーク(CppUnitTestFramework)
GoogleTest
Boost.Test
CTest

## 組み合わせを試す

[x] 初級: IDE + Microsoft 単体テスト
[ ] 基礎: MSBuild + Microsoft 単体テスト
[ ] 基礎: MSBuild + GoogleTest
[ ] 応用: CMake + Microsoft 単体テスト
[ ] 応用: CMake + GoogleTest

## 初級: IDE + Microsoft 単体テスト

IDEを使用して実装とテストをしてみます。
まずはVisual Studio(以下、VS)でソリューションを作ります。

### コンソールアプリを作成する

まずは、新しいプロジェクトの作成→コンソールアプリを選択→次へ
適当な場所に「FizzBuzzApp」というプロジェクト名/ソリューション名でソリューションを作成します。

### プロジェクトファイルの確認

作成したディレクトリには、`FizzBuzzApp.vcxproj`というファイルが生成されています。

### とりあえず規定のターゲットでビルド

`msbuild`にはパスを通しておいてください。

```bat:コマンド
msbuild FizzBuzzApp.vcxproj
```

```text:出力
ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:03.04
```

### cppファイルの追加

`FizzBuzzApp`を右クリックし、[追加]>[クラス]を選択し、`FizzBuzz`クラスを追加します。
追加された.cpp、.hファイルの内容を以下のようにします。

```cpp:FizzBuzz.cpp
#include "FizzBuzz.h"

#include <string>
using namespace std;

string FizzBuzz::fizzbuzz(int num) {
	return "fizz";
}
```

```cpp:FizzBuzz.h
#pragma once
#include <string>
using namespace std;

class FizzBuzz
{
public:
	string fizzbuzz(int num);
};
```

### 単体テストフレームワークの追加

テスト作成のワークフロー[^4]に従って試します。

[^4]: [Visual Studio で C/C++ 用の単体テストを作成する](https://learn.microsoft.com/ja-jp/visualstudio/test/writing-unit-tests-for-c-cpp?view=vs-2022)

以下の2つの手順を実施します:

- Visual Studio 2022 でテスト プロジェクトを作成する
- ソリューション内の他のプロジェクトへの参照を作成する

ここでは、`UnitTest1`をユニットテストとして追加しました。
「オブジェクトまたはライブラリ ファイルのリンク」をするため、テスト実行ファイルにテスト対象をリンク[^5]します。
追加時の値にマクロを使いましたが、マクロボタンから評価後の値を使うと楽に探せます。

[^5]: [テストをオブジェクトまたはライブラリ ファイルにリンクするには](https://learn.microsoft.com/ja-jp/visualstudio/test/how-to-use-microsoft-test-framework-for-cpp?view=vs-2022#object_files)

- [構成プロパティ]>[リンカー]>[入力]の[追加の依存ファイル]には、`FizzBuzz.objを追加します
- [構成プロパティ]>[リンカー]>[全般]の[追加のライブラリ ディレクトリ]には、`$(SolutionDir)\FizzBuzzApp\x64\Debug`を追加します
- [構成プロパティ]>[VC++ ディレクトリ]の[インクルード ディレクトリ]には、@$(SolutionDir)\FizzBuzzApp`を追加します

続いてワークフローに戻り、次の手順を実施します:

- ヘッダー ファイルの #include ディレクティブを追加する
- テスト メソッドを作成する

試しに次のようなテストメソッドを作成しました。

```cpp:UnitTest1.cpp
#include "pch.h"
#include "CppUnitTest.h"
#include "../FizzBuzzApp/FizzBuzz.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{
	TEST_CLASS(UnitTest1)
	{
	public:
		
		TEST_METHOD(_1isFizz)
		{
			string ans = "fizz";
			FizzBuzz obj = FizzBuzz();
			Assert::AreEqual(ans, obj.fizzbuzz(1));
		}
	};
}
```

その後、「テストの実行」に移り、テストを実行します。
後はテストメソッドをどんどん追加するだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164880/f606bba4-4cf2-d617-da4b-165b93458751.png)

### コマンドラインからビルド&テストを実行してみる

メニュー バーで [ツール]>[コマンド ライン]>[開発者コマンド プロンプト]を選択する。
念のため、rebuildターゲットにしてみる。

```console:開発者コマンドプロンプト
msbuild -t:rebuild
cd x64\Debug
vstest.console.exe UnitTest1.dll
Microsoft (R) Test Execution Command Line Tool Version 17.9.0 (x64)
Copyright (c) Microsoft Corporation.  All rights reserved.

テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
  成功 _1isFizz [< 1 ms]
  成功 _2isBuzz [< 1 ms]

テストの実行に成功しました。
テストの合計数: 2
     成功: 2
合計時間: 0.3328 秒
```

### IDE + Microsoft 単体テストの感想

ということで、初級編でもコマンドでビルド&テストできましたね。
ソリューション内の他のプロジェクトへの参照を作成するあたりが少し複雑でした。
ここで得られた知見としては、
- テストの実行ファイルはMS提供のvstest.console.exeを使う
- テストメソッドが入ったオブジェクトはテスト対象とリンクして、dll化する
でした。
また、依存関係の複雑性が上昇したときにメンテナンス&レビューができるか不安な所です。

##  基礎: MSBuild + Microsoft 単体テスト

とりあえず、このチュートリアル[^2]に従って進めます。

[^2]: [チュートリアル: MSBuild を使用した Visual C++ プロジェクトの作成](https://learn.microsoft.com/ja-jp/cpp/build/walkthrough-using-msbuild-to-create-a-visual-cpp-project?view=msvc-170)

完成したプロジェクトファイル[^3]に、Visual Studio 2022に合わせて以下の変更を加えます:

- `ToolsVersion="17.0"`とします
- `PlatformToolset`の要素は`v143`とします

[^3]: [完成したプロジェクト ファイル](https://learn.microsoft.com/ja-jp/cpp/build/walkthrough-using-msbuild-to-create-a-visual-cpp-project?view=msvc-170#complete-project-file)

msbuildを実行して、成果物を実行してみます。

```powershell:ターミナル
.'C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe' .\fizzbuzzapp.vcxproj /p:configuration=debug
```

```terminal:実行してみる
.\debug\fizzbuzzapp.exe
Hello, from MSBuild!
```

```powershell:cleanしてみる
.'C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe' .\fizzbuzzapp.vcxproj /t:clean /p:configuration=release
```

疲れたのでここまで。そのうち追記します。