VSCode で JUnit のカバレッジを表示する

2024 年 3 月に VisualStudioCode にて JUnit のカバレッジがエディタ内で確認できるようになりました。

https://devblogs.microsoft.com/java/java-on-visual-studio-code-update-march-2024/#testing-coverage-available-in-stable-version-of-visual-studio-code

この記事ではその使用方法についてまとめてみました。

# プロジェクトの作成

VSCode からシンプルな Java アプリケーションを作成します。

1. コマンドパレット（Ctrl+Shift+P）を開く
1. 「Java: Create Java Project」を選択
1. Maven を選択してプロジェクトを作成
1. Group Id や Artifact Id、Destination Folder を選択して、ひな形を生成

## pom.xml に JUnit と JaCoCo 関連の設定を追加

pom.xml にて dependency に JUnit を追加します。

```xml:pom.xml
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.11.4</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
```

続いて、同じファイルですが、 build -> plugins に maven-surefire-plugin と JaCoCo のプラグインを追加します。

maven-surefire-plugin は Maven の標準的なテスト実行用プラグインです。これを追加することで JaCoCo とも連携し、テストカバレッジ情報を `target/surefire-reports` 配下に出力してくれます。

JaCoCo はデファクトスタンダード的な存在で Java のコードカバレッジを測定するためのツールです。

```xml:pom.xml
    <!-- 省略 -->

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.12</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
```

## Java のコードを実装

続いて、Java のコードを実装していきます。
今回は、カバレッジ 100% のクラスとわざとカバレッジをいい感じで 100% にさせていないクラスの２つを用意して、それぞれに JUnit のテストコードを作成しています。

```java:FullC0C1LoanEvaluator.java
// 100% 網羅にするテスト対象
public class FullC0C1LoanEvaluator {
    public String evaluateLoan(int creditScore, int income, int loanAmount) {
        if (creditScore < 600) {
            return "REJECTED";
        }

        if (income < 3000000) {
            if (loanAmount > 10000000) {
                return "REJECTED";
            }
            return "FURTHER_REVIEW";
        }

        if (loanAmount > 50000000) {
            if (creditScore < 800) {
                return "FURTHER_REVIEW";
            }
        }

        return "APPROVED";
    }
}
```

```java:PartialC0LoanEvaluator.java
// 部分的網羅なテスト対象
public class PartialC0LoanEvaluator {
    public String evaluateLoan(int creditScore, int income, int loanAmount) {
        if (creditScore < 600) {
            return "REJECTED";
        }

        if (income < 3000000) {
            if (loanAmount > 10000000) {
                return "REJECTED";
            }
            return "FURTHER_REVIEW";
        }

        if (loanAmount > 50000000) {
            if (creditScore < 800) {
                return "FURTHER_REVIEW";
            }
        }

        return "APPROVED";
    }
}
```

```java:FullCoverageTest.java
// 100% 網羅なテスト
class FullCoverageTest {
    private final FullC0C1LoanEvaluator evaluator = new FullC0C1LoanEvaluator();

    @Test
    void testLoanEvaluation_FullCoverage() {
        // 低いクレジットスコアでの即時拒否
        assertEquals("REJECTED", evaluator.evaluateLoan(550, 4000000, 5000000));

        // 低収入での条件分岐
        assertEquals("REJECTED", evaluator.evaluateLoan(650, 2000000, 15000000));
        assertEquals("FURTHER_REVIEW", evaluator.evaluateLoan(650, 2000000, 5000000));

        // 高額ローンでの条件分岐
        assertEquals("FURTHER_REVIEW", evaluator.evaluateLoan(750, 4000000, 60000000));
        assertEquals("APPROVED", evaluator.evaluateLoan(850, 4000000, 60000000));

        // 標準的な承認ケース
        assertEquals("APPROVED", evaluator.evaluateLoan(700, 4000000, 30000000));
    }
}
```

```java:PartialC0CoverageTest.java
// 部分的網羅なテスト
class PartialC0CoverageTest {
    private final PartialC0LoanEvaluator evaluator = new PartialC0LoanEvaluator();

    @Test
    void testLoanEvaluation_FullC1PartialC0() {
        // すべての分岐を網羅
        assertEquals("REJECTED", evaluator.evaluateLoan(550, 4000000, 5000000));
        assertEquals("REJECTED", evaluator.evaluateLoan(650, 2000000, 15000000));
        assertEquals("FURTHER_REVIEW", evaluator.evaluateLoan(750, 4000000, 60000000));
        assertEquals("APPROVED", evaluator.evaluateLoan(850, 4000000, 60000000));

        // 注: 以下の命令は未実行
        // - 低収入で低額ローンのケース
        // - 中程度の収入と低額ローンの標準的な承認ケース
    }
}
```

# テストコードの実行

カバレッジを表示させるためには、アクティビティバーに表示されている Testing ビューから、「Run Test with Coverage」にて実行させる必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/2a951681-8d8e-d33c-0ad3-35e67612c433.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/bf2aadc1-fc68-75f5-103a-a9c105833aaf.png)

:::note info
コマンドなどで、 `mvn clean test` としても JaCoCo のレポートはファイル出力されますが、エディタにカバレッジ情報は反映されません。
:::

テスト実行が終わると、 Testing ビューにて以下のようにカバレッジ情報が反映されます。

## TEST COVERAGE ビュー

テスト実行した下に表示されている 「TEST COVERAGE」にてカバレッジが一覧で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/ac5d46a4-618e-4102-c411-e73e377b9cd5.png)

メーターが３つ並んでいますが、左から statements covered（命令網羅、C0）、functions covered（関数網羅）、branches coverd（分岐網羅、C1）となります。

また、表示されているファイルを並び替えることもでき、例えば、カバレッジが低い順で並び替えると、カバレッジが低くなっているファイルが見つかりやすくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/3c5ba9df-ccd3-4f60-3df0-00fc241ade6a.png)

※ 「TEST COVERAGE」の × ボタンの左側にソートボタンがあります。

## ファイル内での表示

エディタでテスト対象となっていた Java コードを表示すると、どの部分が C0, C1 だったのかが見た目で分かるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/6fb10077-7357-703f-433e-d80f5baf9560.png)

行番号がついているバーに注目すると、３色でパターン分けされていますが、それぞれ緑が C0 かつ C1、背景が緑で赤のメッシュが入っているのが C0 だけ網羅のコード、赤が C0 でも C1 でも網羅されていないコードになります。

また、3x 2x 1x と表示されているのは、テスト時に実行された回数を示しています。

## EXPOLORER ビューでの表示

EXPOLORER でもカバレッジがディレクトリやファイルごとに確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/2a82a4d2-28bb-6ca0-c154-3834e4265420.png)