カバレッジ測定ツール AxoCover をVisual Studio 2019で利用する方法


## 1.前書き

Visual Studioアドイン[AxoCover](https://marketplace.visualstudio.com/items?itemName=axodox1.AxoCover)はVisual Studio 2012 ～ 2017で利用可能な【**`カバレッジ測定ツール`**】です。Visual Studio Enterpriseにもカバレッジ測定機能が組み込まれていますがとても高価ですので、
Community版で利用可能な無償ツールはとてもありがたいです。

* サンプルソース

https://github.com/murasuke/AxoCover-on-VS2019

**ツールの特徴**

* ユニットテストを自動で検出します。
* ユニットテストを実行すると、クラス、メソッド毎にカバレッジ率を表示することができる。
* カバレッジ測定自体はコマンドラインツールの[opencover](https://github.com/OpenCover/opencover)を利用しているようです。アドオンとして統合されているAxoCoverを使えば、細かい設定を意識せずに測定ができます。

  ![AxoCover0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/2c1d4e38-79ff-f539-80d3-3b8cb3373efa.png)

---

## ただし、困ったことにVS2019にはインストールできません

---

なぜならAxoCoverはここ数年、開発が止まっているからです。

それでも[githubのissue上でVS2019対応](https://github.com/axodox/AxoCover/pull/206)について議論がなされており、pre-releaseとしてVS2019に対応した[master-1.1.400](https://github.com/axodox/AxoCover/releases/tag/master-1.1.400)が公開されています。

VS2019で非推奨となったAPIを利用しているため起動時に警告が表示されますが、動作自体に問題はないようです。

(起動時に同期ロードAPIを利用しているため、VisualStudio起動時のパフォーマンスに影響があるようです)


## 2.AxoCoverインストール方法
Visual Studio 2019の「拡張機能の管理」からはインストールができないため、拡張機能(.vsix)をgithubからダウンロードします。


* 1.`AxoCover.vsix`のダウンロード

  [AxoCover.vsix](https://github.com/axodox/AxoCover/releases/download/master-1.1.400/AxoCover.vsix)を、githubからダウンロードします。

* 2.インストール
  
  ダウンロードしたファイルを右クリックして、インストール(開く)を行います。

  ![AxoCover1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/1a7cb20d-50f8-c227-4a9b-d0313ecd1a11.png)


* インストール対象のバージョンを選択して「Install」をクリック

  ![AxoCover2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/33121ab1-69d7-6f16-627b-d10b112d65c3.png)


* Visual Studioが起動していると、インストールを妨げているプロセスを終了してよいか確認する画面が表示されます

  ![AxoCover3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/74b54f97-a3ad-ef9c-de36-d33e7002f6c6.png)


  Visual Studioを手動で終了すると次へ進みます(もしくはEnd Tasksで強制終了して次へ進みます)

* インストール中

  ![AxoCover4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/8dc69cbc-978e-539b-6bec-08c75c4a0143.png)


* インストール完了画面

  ![AxoCover5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/10ca7d0f-fef3-086d-3127-1e82fb53bd60.png)



---

インストール自体はこれで完了ですが、VisualStudio起動時にアドイン読み込みエラーが表示されます。

* Visual Studio 2019を起動後の警告表示

  ![AxoCover6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/19634a57-f8bb-a602-dd04-7d2819604b5d.png)


  ここでは「同期自動読み込みを許可」をクリックして、アドオンの読み込みを継続します。

* AxoCoverの表示

  ![AxoCover8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/6b24fd79-d483-016c-883c-5119c602af25.png)


  「ツール」メニューから選択して表示します


* 初回起動時の確認画面

  ![AxoCover7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/a2be307b-fa5c-a6ad-001d-29065aba87c3.png)


  エラー時にtelemetryを送るかどうか選択して「OK」をクリックします。

* AxoCoverアドオン画面(UnitTestが存在しない場合)

  ソリューション内にUnitTestがない場合、テストコードが見つかりませんよ？という確認の画面が表示されます。

  ![AxoCover9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/15cf09f0-8be4-72e6-75a6-64f0d5715310.png)




* AxoCoverアドオン画面(UnitTestが存在する場合)

  UnitTestがある場合は自動的に検出されて、テストがツリー表示されます。

  ![AxoCover10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/67413751-92ae-55f1-0c86-15ed1c69e7b2.png)




## 3.簡単な動作確認手順

動作確認のため、ごく単純なテスト対象プロジェクト(CalcLogic.cs)と、UnitTestプロジェクトを作成します。

[サンプルソース(github)](https://github.com/murasuke/AxoCover-on-VS2019)

### 3-1. テスト対象プロジェクトの作成

* .NET Frameworkで適当にプロジェクト(exeでもdllでもどちらも可)を作成してテスト対象ソースき下記コードを記載します。

  分岐が1つだけの簡単なロジックです。

```csharp
    public class CalcLogic
    {
        public static decimal Add(decimal a, decimal b)
        {
            return a + b;
        }

        public static decimal Sub(decimal a, decimal b)
        {
            return a - b;
        }

        public static decimal Mul(decimal a, decimal b)
        {
            return a * b;
        }

        public static decimal Div(decimal a, decimal b)
        {
            if (b == 0)
            {
                return 0;
            }

            return a / b;
        }
    }
```



### 3-2. ユニットテストの作成

* ソリューションを右クリックして「単体テストプロジェクト」を追加します

  ![AddTestProject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/a52e3595-d221-e0a8-77d4-beb9813cd434.png)


* 適当にプロジェクト名を決めて(UnitTestProject)作成します。（作成後、テスト対象のプロジェクトを参照に追加してください）

  UnitTestコードは下記のようになります。

```csharp
    [TestClass]
    public class TestCalcLogic
    {
        [TestMethod]
        public void TestAdd()
        {
            Assert.AreEqual(CalcLogic.Add(1, 2), 3);
        }

        [TestMethod]
        public void TestSub()
        {
            Assert.AreEqual(CalcLogic.Sub(1, 2), -1);
        }

        [TestMethod]
        public void TestMul()
        {
            Assert.AreEqual(CalcLogic.Mul(1, 2), 2);
        }

        [TestMethod]
        public void TestDiv()
        {
            Assert.AreEqual(CalcLogic.Div(1, 2), 0.5M);
            //Assert.AreEqual(CalcLogic.Div(1, 0), 0M); // 分岐を100%にしないためにコメントアウト
        }
    }
```

### 3-3. AxoCoverでカバレッジ測定

  AxoCoverを表示すると、UnitTestがツリー状に表示されます。赤枠で囲った「Cover」をクリックすると、選択されている部分のUnitTestが行われてから、カバレッジ測定の結果が表示されます。

* 測定前

  ![AxoCover10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/265454ca-de71-0fed-00ab-bb47b758b01b.png)




* 測定後（UnitTest実行結果）

  全てのテストが正常に終了。

  ![result1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/8ef50b7b-80a2-3da6-9978-d5fef1b8a251.png)



* 測定後（Reportタブ）

  テスト対象のうち「`Div()`」メソッドの分岐カバレッジが100%になっていません。

  ![result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/36c7ea75-a899-1c47-024f-87e5290ab3d6.png)


  右下の「`Source`」をクリックすることで、該当ソースを開いてカバレッジの詳細を確認することができます。

  `b == 0`の場合の分岐が通っていないことが一目瞭然です。
  
  ![result3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/b1dc2cb2-b85a-3ab3-1254-459dd088ae0e.png)



### 3-4. UnitTestを修正して再確認

* TestDiv()メソッドのコメントを外して、再度UnitTestを実行します

```csharp
    [TestClass]
    public class TestCalcLogic
    {

        [TestMethod]
        public void TestDiv()
        {
            Assert.AreEqual(CalcLogic.Div(1, 2), 0.5M);
            Assert.AreEqual(CalcLogic.Div(1, 0), 0M); // 分岐を網羅するためコメントアウトを削除
        }
    }
```

* 無事、分岐網羅率が100%になりました(C1網羅)

  ![result4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/5880f764-48fd-d86d-8652-d45c158bf38e.png)

## 4.手動操作(テスト)時にカバレッジ測定を行う方法について

AxoCoverは、ユニットテストを自動的に検出して実行するのと同時にカバレッジ測定を行います。
これでは、個別にプログラムを起動して手動で動作確認を行うことができません。

実は、ユニットテストコードからテスト対象フォームを起動し、手動でテストを行うことでカバレッジを測定することが可能です。


* テスト対象フォーム起動ユニットテストコード

```csharp
namespace ManualTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void ManualTest()
        {
            // Show form, and test manualy
            TestTargetExeForm.Program.Main();
            
        }
    }
}
```

* フォーム起動用ユニットテストを選んでテストを実行します。

![AxoCover11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/3629faae-de46-da2c-6e70-6096f66988be.png)


* テスト対象フォームが起動します。手入力で「1 - 2」を入力して「計算ボタン」を押下します。

  ![AxoCover12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/c6caa744-7a35-ccd6-7bbe-683020a34d5e.png)

* プログラムを「×」ボタンで閉じるjとカバレッジ測定結果が表示されます。引き算のみ実行されたことがわかります。


![AxoCover13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/572d44f9-1597-48b2-f028-13f41268c7d3.png)

## その他調査

|  確認内容  |  結果  | 補足 |
| ---- | ---- | ---- |
| テスト対象が.NET2.0、UnitTestが.NET4.8の場合でもカバレッジ測定は可能か？ | 可能  | |
| UnitTestプロジェクトのフレームワークを.NET4.0にしても測定は可能か？  |  不可  |　MSTest.TestFrameworkが.NET4.5以降を要求するため |
| プロジェクト参照、通常のdll参照どちらでもカバレッジ測定はできるか？ | 可能 |  |