jacoco で gradle のマルチモジュール構成のカバレッジを集計する
N年ぶり、M回目で gradle を利用しているマルチモジュールプロジェクトのコードカバレッジ集計を jacoco で設定する方法を調べた。
毎回毎回調べてるのでいい加減メモを残そうというもの。
と思い、調べてみるとちょっと前にやってた方法は結構泥臭くやっていた気がしていたのだけれど、以下2つの Gradle のページだけで解決してしまった。
The JaCoCo Plugin
Reporting code coverage with JaCoCo Sample
TL;DR
Root Project
plugins {
// ...
id("jacoco")
}
// ...
jacoco {
toolVersion = "0.8.7"
}
tasks.register<JacocoReport>("codeCoverageReport") {
subprojects {
val subproject = this
subproject.plugins.withType<JacocoPlugin>().configureEach {
subproject.tasks.matching { it.extensions.findByType<JacocoTaskExtension>() != null }.configureEach {
val testTask = this
sourceSets(subproject.sourceSets.main.get())
executionData(testTask)
}
subproject.tasks.matching { it.extensions.findByType<JacocoTaskExtension>() != null }.forEach {
rootProject.tasks["codeCoverageReport"].dependsOn(it)
}
}
}
reports {
xml.isEnabled = true
html.isEnabled = true
}
}
Sub Projects
テストカバレッジを集計したいサブプロジェクトに以下を適用する
plugins {
// ...
id("jacoco")
}
// ...
jacoco {
toolVersion = "0.8.7"
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
}
カバレッジ集計
そして以下を実行すれば、 /build/reports/jacoco/codeCoverageReport/
にレポートが出力される。
./gradlew clean codeCoverageReport
タスクの依存関係
上記のようなタスクの依存関係になっていて、それぞれのタスクは単独で実行可能になっている。 (実行されると dependsOn
で依存しているタスクも実行される。)
codeCoverageReport
は唯一新規に定義するタスクで他のものは、 プラグインのものに dependsOn
を設定しているだけである。
codeCoverageReport
JacocoReport にもある通りなんですが、特に注目するプロパティは、以下の2つ
- executionData
- sourceSets
executionData
は jacoco プラグインを適用すると自動で作成してくれる build/jacoco/xxx.exec
を与えるとカバレッジを集計してくれる。
カバレッジのデータを与えるだけではだめで、対象となるソースコードも与える必要があるので sourceSets
に対象となるソースコードを適用してあげる。
これだけで、すべての jacoco プラグインが適用されているサブプロジェクトのテストカバレッジレポートを1つのレポートとして集計することができる。
その他
Kotlin のプロジェクトで jacoco 0.8.6以前を利用した場合
今回に直接関係ないが、自分の現在の環境ではデフォルトで jacoco のバージョンが 0.8.6.x
の最新版が適用されていた。
これで実行すると、 https://github.com/jacoco/jacoco/issues/1155 にある通り、Kotlin 1.5系での形式を読み込めずにタスクがエラーになってしまうケースに遭遇した。
./gradlew clean codeCoverageReport --stacktrace
のように --stacktrace
オプションでエラーの内容を見ることができるのでそこでわかる。