C#でMSTestのカバレッジ計測をしてみる

# 1. はじめに
* C#で作成した単体テストのカバレッジを計測したい
* Visual Studio EnterpriseだとGUIでカバレッジが取得できるが、高価になるのでフリーのツールで代替したい

# 2. 開発環境
* Widnows 11
* Visual Studio 2022 Community
* MSTEST
* OpenCover (Nuget)
* ReportGenerator (Nuget)

# 3. 開発環境準備
* NuGetよりインストールする
## 3.1. OpenCoverのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/ea722951-14e0-b2fe-911b-dd69044f41dd.png)

## 3.2. ReportGeneratorのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/45c40989-f006-6080-694f-fb32c2f42f45.png)

# 4. サンプルプログラム
# 4.1. Calculatorクラス (テスト対象)
* 新規クラスを追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/0d99987d-b0e3-97ef-8f87-f3aeed72da95.png)

* 足し算をする簡単なメソッドを追加
```csharp:Calculator.cs
    public class Calculator
    {
        public Calculator()
        {
            // Do Nothing
        }

        /// <summary>
        /// 足し算をする
        /// </summary>
        /// <param name="x">値1</param>
        /// <param name="y">値2</param>
        /// <returns>値1 + 値2</returns>
        public int Add(int x , int y)
        {
            return x + y;
        }
```
* 念のため動作確認をする
```csharp
        private void Form1_Load(object sender, EventArgs e)
        {
            // 足し算する
            var calculator = new Calculator();
            var result = calculator.Add(1, 2);

            // デバッグ用
            Debug.Print(result.ToString());
        }
```

# 4.2. テストクラス作成
* テスト対象のメソッドを選択して、右クリックから```単体テストの作成```を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/612f8d93-0ab7-08d8-77c5-c6470c5ede83.png)

* OKボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/19246a4e-5d34-8618-453f-9498e8bb8e46.png)

* 足し算を確認する処理を追加する
```csharp
    [TestClass()]
    public class CalculatorTests
    {
        [TestMethod()]
        [TestCategory("UnitTest")]
        public void AddTest()
        {
            // 期待値
            int expected = 3;

            // 実行結果
            var calculator = new Calculator();
            int actual = calculator.Add(1, 2);

            // テスト検証
            Assert.AreEqual(expected, actual);
        }
    }
```

* 単体テストを実行して成功になることを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/aec19e92-77bd-21a0-62ff-a89787198b99.png)

# 5. カバレッジ取得
* OpenCover, ReportGeneratorを使用する場合、GUI上では実施できないためバッチファイルを作成する
* 実行結果はHTMLへ出力してブラウザ上で確認できるようにする

## 5.1. バッチファイル作成
* 今回ソリューションフォルダの直下に作成した
```
@echo off
rem OpenCoverのインストール先
SET OPEN_COVER=%USERPROFILE%\.nuget\packages\opencover\4.7.1221\tools

rem Report生成ツールのインストール先
SET REPORT_GEN=%USERPROFILE%\.nuget\packages\reportgenerator\5.1.18\tools\net6.0

rem テストフレームワークのインストール先
SET MS_TEST=%ProgramFiles%\Microsoft Visual Studio\2022\Community

rem ターゲットアセンブリ (テストクラスがあるDLLファイル) 
SET TARGET_TEST=WinFormsApp2Tests.dll

rem ターゲットアセンブリの格納先 (テストクラスがある場所)
SET TARGET_TEST_DIR=C:\Users\user\source\repos\WinFormsApp2\WinFormsApp2Tests\bin\Debug\net6.0-windows

REM カバレッジ計測対象 (テスト対象クラスのNAMESPACE)
SET FILTERS="+[WinFormsApp2]*"

REM パスの設定
SET PATH=%PATH%;%OPEN_COVER%;%MS_TEST%;%REPORT_GEN%

REM OpenCoverを実行 (./CoverageReportフォルダへ結果出力)
OpenCover.Console -register:user -target:"%MS_TEST%\Common7\IDE\Extensions\TestPlatform\vstest.console.exe" -targetargs:"%TARGET_TEST%" -targetdir:"%TARGET_TEST_DIR%" -filter:"%FILTERS%" -output:".\CoverageReport\result.xml"

REM ReportGeneratorrを実行 (./CoverageReportフォルダへ結果出力)
ReportGenerator -reports:".\CoverageReport\result.xml" -reporttypes:Html -targetdir:".\CoverageReport"

pause
```

## 5.2. バッチファイル実行
* Visual Studioでビルドした後にバッチファイルを実行する
* 初回は原因不明のエラーが出たが、2回目からは正常終了した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/17651775-095a-f26f-6529-743b856afa91.png)

## 5.3. ReportGeneratorのレポート確認
* ブラウザでカバレッジを確認して想定通り出力されていることを確認した
* staticのクラスの確認方法はまだ対応方法を検討中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/b5653022-3269-1f40-aac0-f138dcf15162.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/9e89fa21-7d02-1614-2cb3-64c7de3ccbff.png)

# 6. 参考文献
http://country-programmer.dfkp.info/2020/04/windows_opencoverage_001/