0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kover 登場前の JaCoCo による Android のローカル単体テストのカバレッジレポート出力は難しかった

Posted at

この記事は「Kover でらくらく! Android のカバレッジレポート出力」の補足となります。

Gradle でカバレッジレポートを出力する設定方法は、Codecov 公式で JaCoCo Plugin を使う方法が紹介されています。しかし Android のローカル単体テストを対象とする場合の設定が難解です。近年、Kotlin 公式のプラグインである Kover がリリースされ、それを使用することで、 最短2行のシンプルな記述でカバレッジレポートの出力を設定できるようになりました。

と言いましたが、JaCoCo Plugin はどのくらい難解だったのかを解説します。

開発スタイルおよび環境

この記事では元の記事と同様の開発スタイルおよび環境を想定しています。

バイナリ形式のカバレッジレポートを出力する

プロジェクトの build.gradle を編集して設定します。

まず、すべてのモジュールで jacoco プラグインを使うようにします。

build.gradle
allprojects {
    apply plugin: 'jacoco'
}

すると単体テストタスク実行時に testDebugUnitTest.exec がモジュールごとに出力されるようになります。(Debug の部分は Build Variant)

./gradlew testDebug
find . -type f -name *.exec
./app/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./feature/home/usecase/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./feature/home/presentation/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./feature/info/compose/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./feature/info/usecase/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./feature/info/presentation/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./data/repository/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./data/local/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./data/remote/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec
./viewCommon/build/outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec

このファイルの中身はバイナリ形式となっています。

スクリーンショット 2023-07-10 4.05.57.png

このままでは人間は読めませんし、Codecov でも非対応のフォーマットとなっています。

バイナリ形式のカバレッジレポートを HTML および XML 形式のカバレッジレポートに変換する

Codecov は XML 形式のカバレッジレポートに対応しています。また、Gradle タスクのデバッグや Codecov を使わない運用のために、HTML 形式にも変換します。

そのために JaCoCo プラグインで以下のような変換を行います。

kt ファイル + class ファイル + exec ファイル ⇒ HTML/XML 形式のカバレッジレポート

プロジェクトの Gradle ファイルに以下の記載を追加することで実現できます。

build.gradle

// jacocoReport タスクを作成
tasks.register("jacocoReport", JacocoReport) {
{
    // XML 形式 と HTML 形式の両方のカバレッジレポートを出力する
    reports {
        xml.required.set(true)
        html.required.set(true)
    }
    // 全モジュールの kt ファイルのディレクトリ一覧
    def mySourceDirectories = subprojects.collect { project ->
        "${project.projectDir}/src/main/java"
    }
    // 全モジュールの class ファイルのディレクトリ一覧
    def myClassDirectories = subprojects.collect { project ->
        "${project.buildDir}/tmp/kotlin-classes/debug"
    }
    // exec ファイル一覧
    def execFileTree = fileTree(dir: rootDir, includes: [
            "**/testDebugUnitTest.exec"
    ])
    // それらを JacocoReport タスクの設定値とする
    sourceDirectories.setFrom(mySourceDirectories)
    classDirectories.setFrom(myClassDirectories)
    executionData.setFrom(execFileTree)
}

これで jacocoReport タスクの実行で XML 形式 と HTML 形式のカバレッジレポートが出力されます。

./gradlew jacocoReport

出力先はこちらです。

XML 形式 build/reports/jacoco/jacocoReport/jacocoReport.xml
HTML 形式 build/reports/jacoco/jacocoReport/html/index.html

HTML 形式のレポートはこのように出力されます。

スクリーンショット 2023-07-15 1.15.44.png

jacocoReport タスクだけでカバレッジレポートを出力する

これまでの設定ではカバレッジレポートを出力するために、2つのタスク実行が必要です。

./gradlew testDebug
./gradlew jacocoReport

1タスクで完結するために、タスクの依存関係を設定します。

build.gradle
tasks.register("jacocoReport", JacocoReport) {
    // 全モジュールの testDebugUnitTest タスク一覧
    def tasks = subprojects.findAll { project ->
        // モジュールでないディレクトリも列挙されるので、build.gradle が存在するものだけを対象とする。
        project.file("build.gradle").exists()
    }.collect { project ->
        "$project.path:testDebugUnitTest"
    }
    // それらが完了してから、このタスクを実行する
    dependsOn(tasks)
    
    // 以下、前の節ど同じ
}

これで jacocoReport タスクだけでカバレッジレポートが出力されるようになります。

./gradlew jacocoReport

カバレッジレポート対象クラスを制限する

例えば ViewModel クラスだけなど、カバレッジレポート対象クラスを制限する方法も紹介します。freeTree メソッドを使い、対象クラスの class ファイルだけ指定すれば良いです。

build.gradle

// jacocoReport タスクを作成
tasks.register("jacocoReport", JacocoReport) {
{
    // 全モジュールの対象 class ファイル一覧
    def classFileTrees = subprojects.collect { project ->
        fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/debug",
                includes: ["**/*ViewModel.class"]
        )
    }
    classDirectories.setFrom(classFileTrees)
}

まとめ

この記事では JaCoCo Plugin で Android のローカル単体テストのカバレッジレポート出力の設定方法を解説しました。最短2行で設定が完了する Kover に対して、JaCoCo Plugin では Gradle のタスクを作成したり、kt ファイル、class ファイル、exec ファイルのパスを指定する必要があったりと難解です。すでに設定済みならばともかくとして、これから設定する場合は Kover の方がおすすめです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?