JaCoCoでJavaのテストカバレッジのレポートを出力する

最近、機能によって品質水準がバラバラなJavaのプログラムと格闘してます。
こんなときにどんなアプローチがあるかなーと考えた結果、ソースコードのカバレッジを出力するとおおよその品質がつかめそうだということで、レポートを出力して可視化することを考えました。

今回はとりあえず練習として、既存のMavenやGradleのプロジェクトに対してレポートを出力してみることにしました。

ソースコードを可視化するツールについて

Qiitaのこちらの記事によると、以下が主要ライブラリなようです。

しかしコミュニティの活発度を見たところ、JaCoCo一択のようです。
Coberturaは最終リリースが2015年ですし、Cloverも最後のコミットが2017年です。
JaCoCoは2019年が最終リリースなので、まだ活動が期待できます。

また、実は自身は今までにJaCoCoを間接的に使ったことがあるということが分かりました。
以前、Eclipseでコードカバレッジを測定するときにはEclEmmaというプラグインを使っていたのですが、この中に組み込まれているカバレッジの測定ライブラリがJaCoCoということのようです。
そのため、自分の中では実績十分と判断しました。(そもそも選択肢がほとんどなかったのですが…)

なお、最近はCodecovというカバレッジ可視化のWebサービスも見かけますが、残念ながらローカルでは動かせないようです。
OSSの開発にはお手軽に導入できそうですが、商用開発には向かない場合があるため、Codecovは見送ることにしました。

MavenでJaCoCoのテストレポートを出力

まずはMaven。 あまり影響ないとは思いますが、一応環境やツールのバージョンを記載しておきます。

  • MacOS 10.14.6
  • Maven 3.6.3
  • Git 2.20.1
  • AdoptOpenJDK 1.8.0_212

ソースコードの準備

MavenのプロジェクトサンプルとしてJsoupを使わせていただきました。

git clone https://github.com/jhy/jsoup.git

Mavenを使っているプロジェクトならなんでもよかったのですが、ときどきお世話になっているライブラリので、これを選んでみました。

Mavenの設定ファイルの変更

pom.xmlを編集し、設定を追記します。

<build>の中にある<plugins>の要素として、ここから〜ここまでを追加。

<build>
  <plugins>
    <!-- ここから -->
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.5</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>の要素として、ここから〜ここまでを追加。

<project>
  <!-- ここから -->
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <reportSets>
          <reportSet>
            <reports>
              <report>report</report>
            </reports>
          </reportSet>
        </reportSets>
      </plugin>
    </plugins>
  </reporting>
  <!-- ここまで -->
</project>

テストレポートの出力

テストレポートを出力するには、以下のようにtestの後にjacoco:reportを実行します。

mvn test jacoco:report

すると、target/site/jacoco/index.htmlに以下のようなレポートが出力されます。 test-report-by-jacoco

リンクを辿っていくと、テストが不十分な箇所は以下のようにハイライトされたソースコードが見れます。 code-highlight-by-jacoco

GradleでJaCoCoのテストレポートを出力

次はGradleでやってみます。

  • MacOS 10.14.6
  • Git 2.20.1
  • AdoptOpenJDK 1.8.0_212

ソースコードの準備

Gradleを使っているプロジェクトサンプルとしてJIGを使わせていただきました。

git clone https://github.com/dddjava/jig

Gradleを使っているプロジェクトならなんでもよかったのですが、大御所はあまりGradleを使っていないようです。
Gradleを使っていそうな身近なコミュニティ関係を探った結果、ここに辿り着きました。

Gradleの設定ファイルの変更

build.gradleに設定を追記します。

Gradleはシンプルなプロジェクトでデフォルトのレポートを出力するだけであれば、pluginsの中に以下の一行だけ追加すればよいようです。

plugins {
    // 省略
    id 'jacoco'  // この行を追記するだけ
}

が、JIGではプロジェクトが複数定義されているので、以下のようにそれぞれのプロジェクトでプラグインを適用します。1

project(':jig-core') {
    apply plugin: 'java-library'
    apply plugin: 'maven-publish'
    apply plugin: 'com.jfrog.bintray'
    apply plugin: 'org.dddjava.jig-gradle-plugin'
    apply plugin: 'jacoco'  // この行を追記

    // 省略
}

project(':jig-cli-kt') {
    apply plugin: 'org.springframework.boot'
    apply plugin: 'org.jetbrains.kotlin.jvm'
    apply plugin: 'jacoco'  // この行を追記

    // 省略
}

project(':jig-gradle-plugin') {
    apply plugin: "java-gradle-plugin"
    apply plugin: 'com.gradle.plugin-publish'
    apply plugin: 'maven-publish'
    apply plugin: 'jacoco'  // この行を追記
}

テストレポートの出力

テストレポートを出力するには、以下のようにtestの後にjacocoTestReportを実行します。

./gradlew test jacocoTestReport

通常はbuild/reports/jacoco/test/html/index.htmlに出力されますが、今回は[プロジェクト名]/build/reports/jacoco/test/html/index.htmlにそれぞれ出力されます。
Mavenの場合と同様、以下のようなレポートが確認できました。 test-report-by-jacoco

まとめ

MavenとGradleで、それぞれ既存のプロジェクトにJaCoCoのテストレポートを組み込むことができました。
C0とC1のカバレッジが集計できるので、コードレビュー時にはカバレッジの観点からテストケース不足を指摘することも容易になりそうです。

またJavaのテストはGroovyで書く人も多いと思いますが、以下のような場合でもカバレッジは問題なく取れているようでした。

  • Groovyでテストコードを記述
  • GroovyのSpockを使ってテストコードを記述

テストレポートの出力もかなりお手軽なことが分かったので、CIとして簡単に組み込むことができそうです。

References


  1. jig-cliについてはテストコードが存在しなかったので、適用しなかった ↩︎

関連記事


  1. JJUG CCC 2019 Springに参加してきました
  2. 既存コードへのCheckstyle導入におけるルールの選定
  3. Checkstyleで汎用的に使えそうなルールをピックアップしてみた
  4. MavenでOSSのライセンス一覧を出力する
  5. Groovyの'=='演算子は'equals()'と厳密に同じではない
  6. DDLを自動生成してJavaと各DBのデータ型を比較してみた
  7. Spring Fest 2019に参加しました

comments powered by Disqus