GradleでマルチプロジェクトのJUnit ReportとJacoco Reportを出す
Gradleのマルチプロジェクトを使う必要があって、だいぶハマったので記事に残しておこうと思う。
マルチプロジェクト構成
- root
- myproject
- myproject-test
ここでは、実際のディレクトリとしてフラットに存在する例
$ ls myproject myproject-test root
root
親プロジェクト。 最初はsettings.gradleしか持っていない状態。
settings.gradle
includeFlat "myproject", "myproject-test"
includeで階層型になる。参考
myproject
プロダクトコードプロジェクト。 ここにもJUnitテストコードがあったりする。
myproject-test
myprojectプロジェクトのテスト用プロジェクト。 単体・結合・総合テスト用JUnitが置かれたりする。
現状の問題点
このままgradle test jacocoTestReport
したら、myproject・myproject-testのbuildにそれぞれレポートが出力される。
- root
- myproject
- build
- jacoco - test.exec
- reports
- jacoco - html - index.html
- tests - index.html
- build
- myproject-test
- build
- jacoco - test.exec
- reports
- jacoco - html - index.html
- tests - index.html
- build
これだとJenkinsで管理するときにレポートが上手く行かなくて困る。
myprojectとmyproject-testのJUnit,Jacocoレポートを一括、まとめて、統合、結合でレポートしたい!
JUnit Report
23.13. テスト - gradle userguide
-> 例23.14 Creating a unit test report for subprojects
ここに書いてあるんだけど、なんでか英語のまま!(激怒)
root/build.gradle
subprojects { apply plugin: 'java' test { // 別タスクで一括で出力する reports.html.enabled = false } } task testReport(type: TestReport) { destinationDir = file("$buildDir/reports/allTests") reportOn subprojects.tasks.test }
はまりどころは、apply plugin: 'java'
が必須というところ。
これはGradleの知識がまだ不足してたからだけど、rootからsubprojectを見た時に定義されてないとダメポ
myprojectとかmyproject-testで
apply plugin: 'java'
してるからrootではいらないかな?
とかいうのが落とし穴でした。
結果レポート出力
ということで、rootにtestReportというTaskを追加したので、実行する。
$ cd root $ gradle clean test testReport :myproject:clean :myproject-test:clean :myproject:compileJava :myproject:processResources UP-TO-DATE :myproject:classes :myproject:compileTestJava :myproject:processTestResources UP-TO-DATE :myproject:testClasses :myproject:test :myproject-test:compileJava :myproject-test:processResources UP-TO-DATE :myproject-test:classes :myproject-test:compileTestJava :myproject-test:processTestResources UP-TO-DATE :myproject-test:testClasses :myproject-test:test :testReport BUILD SUCCESSFUL Total time: 19.366 secs
- root
- build
- reports
- allTests - index.html
- reports
- build
- myproject
- myproject-test
myproject
とmyproject-test
にはreportsは出力されてない。OK
Jacoco Report
お次はJacoco Reportをまとめて出力します。
maven時代はcovertura使ってたんだけどなんだか最近はjacocoがいいのかな?ってことでこちらを使ってます。
このGithub Gistを参考にしました。
Aggregated Jacoco reports in a multi-project Gradle build
あとは公式説明書
Chapter 34. The JaCoCo Plugin
DSLも見ないと全然わかりません。
DSL - JacocoReport
Projectのプロパティも使うので、DSL見ます。
DSL - Project
root/build.gradle
allprojects { apply plugin: 'java' apply plugin: 'jacoco' repositories { jcenter() } } subprojects { test { // 別タスクで一括で出力する reports.html.enabled = false jacoco { //execをrootprojectに出力する destinationFile = file("$rootProject.buildDir/jacoco/${project.name}.exec") } } } task testReport(type: TestReport) { destinationDir = file("$buildDir/reports/allTests") reportOn subprojects.tasks.test } task jacocoRootReport(type: JacocoReport) { dependsOn = subprojects.test //レポート対象はmyprojectのソース additionalSourceDirs = files(project('myproject').sourceSets.main.allSource.srcDirs) sourceDirectories = files(project('myproject').sourceSets.main.allSource.srcDirs) classDirectories = files(project('myproject').sourceSets.main.output) //レポートのためのexecはjacocoTestReportタスクの設定を利用 executionData = files(subprojects.tasks.jacocoTestReport.executionData) reports { html.enabled = true xml.enabled = false csv.enabled = false } }
- ハマリポイント
- rootprojectにもjacoco pluginが必要
- jacocoRootReportタスクでjacocoのクラスパスを要求されるので、plugin applyしておかないと怒られます。
- カバレッジ対象はmyprojectのソースにしたい
- projectのプロパティの使い方がいまいちよくわからないのが問題で、かなりはまった。
- jacoco execをrootprojectに出したい
- ハマった原因はやっぱりprojectのプロパティがよくわからなかったから。
- rootprojectにもjacoco pluginが必要
結果レポート出力
結果がわかりやすいようにJavaファイルを変更しました。
- myproject
- myproject-test
それではタスク実行。
$ cd root $ gradle clean jacocoRootReport :clean :myproject:clean :myproject-test:clean :myproject:compileJava :myproject:processResources UP-TO-DATE :myproject:classes :myproject:compileTestJava :myproject:processTestResources UP-TO-DATE :myproject:testClasses :myproject:test :myproject-test:compileJava :myproject-test:processResources UP-TO-DATE :myproject-test:classes :myproject-test:compileTestJava :myproject-test:processTestResources UP-TO-DATE :myproject-test:testClasses :myproject-test:test :jacocoRootReport BUILD SUCCESSFUL Total time: 21.308 secs
- root
- build
- jacoco
- myproject-test.exec
- myproject.exec
- reports
- jacoco - jacocoRootReport - html - index.html
- jacoco
- build
myprojectのソースだけがカバレッジ対象になってます!
なんつーか一番はまりやすいのはprojectのプロパティの使い方だなーとかなり思ってます。
略式記法がわかりづらすぎる・・・
はてなダイアリーからブログに移行しました。