Android Multi-Module Jacoco集成实践

529 阅读1分钟

这里我们不说原理,只说集成过程且只统计单元测试的代码覆盖率

1.创建jacoco.gradle文件

首先在项目根目录创建script文件夹,然后jacoco.gradle如下:

apply plugin: 'jacoco'

tasks.withType(Test) {
    jacoco {
        includeNoLocationClasses = true
        excludes = ['jdk.internal.*'] // Allows it to run on Java 11
    }
}

android {
    testCoverage {
        jacocoVersion "0.8.10"
    }
    buildTypes {
        debug {
            testCoverageEnabled true
        }
    }
}

// 根据你productFlavor和buildType定义
def sourceName = 'devDebug'
def testTaskName = "test${sourceName.capitalize()}UnitTest"

// 如果需要统计androidTest的覆盖率,需要把createDevDebugCoverageReport这个task加到dependsOn里
// createDevDebugCoverageReport - this task for generate androidTest report, that need connect a devices
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDevDebugUnitTest']) {
    group = "JacocoReport"
    description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."

    reports {
        xml.getRequired().set(true)
        csv.getRequired().set(false)
        html.getRequired().set(true)
        // 这里重新定义jacoco生成的报告的位置
        //to create coverage report in html
        html.outputLocation.set(file("${buildDir}/reports/coverage"))
        //for XML
        xml.outputLocation.set(file("${buildDir}/reports/jacoco.xml"))
    }

    def fileFilter = [
            // adapters generated by moshi
            '**/*JsonAdapter.*',
            //dao dir generated by room
            '**/dao/**',
            // Injector generated by hilt
            '**/*GeneratedInjector.*',
            '**/*EntryPoint.*',
            // data binding
            '**/databinding/**/*.class',
            '**/databinding/*Binding.class',
            '**/databinding/*',
            '**/bumptech/*',
            '**/BR.*',
            // android
            '**/R.class',
            '**/R$*.class',
            '**/BuildConfig.*',
            '**/Manifest*.*',
            '**/*Test*.*',
            'android/**/*.*',
            // kotlin
            '**/*MapperImpl*.*',
            '**/*$ViewInjector*.*',
            '**/*$ViewBinder*.*',
            '**/BuildConfig.*',
            '**/*Component*.*',
            '**/*BR*.*',
            '**/Manifest*.*',
            '**/*$Lambda$*.*',
            '**/*Companion*.*',
            '**/*Module*.*',
            '**/*Dagger*.*',
            '**/*Hilt*.*',
            '**/*MembersInjector*.*',
            '**/*_MembersInjector.class',
            '**/*_Factory*.*',
            '**/*_Provide*Factory*.*',
            '**/*Extensions*.*',
            // sealed and data classes
            '**/*$Result.*',
            '**/*$Result$*.*'
    ]

    def javaClasses = []
    def kotlinClasses = []
    def javaSrc = []

    rootProject.subprojects.each { proj ->
        // ignore app project that contain many deprecated code
        if (proj.name != 'app') {
            javaClasses << fileTree(dir: "$proj.buildDir/intermediates/javac/$sourceName/classes", excludes: fileFilter)
            kotlinClasses << fileTree(dir: "$proj.buildDir/tmp/kotlin-classes/$sourceName", excludes: fileFilter)
            javaSrc << "$proj.projectDir/src/main/java"
        }
    }

    sourceDirectories.from = files([javaSrc])
    classDirectories.from = files([javaClasses, kotlinClasses])
    // 这里注意定义executionData的文件夹位置
    def executionDir = "${project.buildDir}/outputs/unit_test_code_coverage/${sourceName}UnitTest/${testTaskName}.exec"
    executionData.from = files(executionDir)
    print("executionData Dir:$executionDir")
}

由于最新版Android Studio生成.exec文件的位置不再是build/jacoco,所以这里要定义具体生成.exec文件的位置。
具体位置如下:

微信图片_20230530123711.png

2.配置Jacoco

首先classpath

classpath('org.jacoco:org.jacoco.core:0.8.10')

然后在app下的gradle加入

apply("${project.rootDir}/script/jacoco.gradle")

在每一个非Application的gradle下加入

plugins {
    id("com.android.library")
    id("jacoco")
}

android {
    buildTypes {
        debug {
            isTestCoverageEnabled = true
        }
    }
}

3.命令行得到代码覆盖率统计报告

待工程Sync完成以后就可以运行一下Command得到测试代码覆盖率的报告

./gradlew app:jacocoTestReport

最后查看App下的build文件夹

微信截图_20230530125408.png

在coverage下的html里查看具体情况。