我目前正在我的团队构建的Android代码库中设置Jacoco.我对Android没有太多经验,但我以前在Spring Boot代码库中设置过Jacoco,这样我就可以在Sonarqube中跟踪测试覆盖率.但我在Android代码库方面做得很艰难.

因此,目录布局如下所示

MyApp/
├─ app/
│  ├─ build/
│  ├─ src/
│  ├─ build.gradle.kts
├─ buildSrc/
│  ├─ build.gradle.kts
├─ modules/
│  ├─ module1/
│  │  ├─ src/
│  │  ├─ build.gradle.kts
│  ├─ module2/
│  │  ├─ src/
│  │  ├─ build.gradle.kts
├─ build.gradle.kts
├─ gradle.properties
├─ gradlew
├─ settings.gradle.kts

我试着在MyApp/build.gradle.kts中加jacoco.

plugins {
    id(Dependencies.Plugins.androidApplication) version Dependencies.Versions.androidAppplication apply false
    id(Dependencies.Plugins.androidLibrary) version Dependencies.Versions.androidLibrary apply false
    id(Dependencies.Plugins.hilt) version Dependencies.Versions.hilt apply false
    id(Dependencies.Plugins.openApi) version Dependencies.Versions.openApi
    id(Dependencies.Plugins.kotlinAndroid) version Dependencies.Versions.kotlinAndroid apply false
    id(Dependencies.Plugins.sonarqube) version Dependencies.Versions.sonarqube
    
    id("jacoco")
}

我试着处死bash gradlew test jacocoTestReport人,但上面写着

Task 'jacocoTestReport' not found in root project 'MyApp' and its subprojects.

根据JaCoco插件文档(https://docs.gradle.org/current/userguide/jacoco_plugin.html),我try 在MyApp/build.gradle.kts中添加以下代码行

tasks.test {
    finalizedBy(tasks.jacocoTestReport) // report is always generated after tests run
}
tasks.jacocoTestReport {
    dependsOn(tasks.test) // tests are required to run before generating the report
}

但输出内容如下所示

Script compilation errors:

  Line 12: tasks.test {
                 ^ Unresolved reference: test

  Line 13:     finalizedBy(tasks.jacocoTestReport)                                              
               ^ Unresolved reference: finalizedBy

我在一个运行正常的Spring Boot项目中进行了类似的配置.但在这里,它甚至无法检测到任务jacocoTestReport.

我做错什么了?

推荐答案

在传统的Java或Kotlin JVM项目中,只有一个测试任务,可以通过tasks.test访问.

然而,在Android项目中,没有一个test任务.相反,有多个测试任务,one for each build variant个.测试任务命名为test<Variant>UnitTest.例如,您可能有testDebugUnitTesttestReleaseUnitTest.

当您try 访问Android项目中的tasks.test时,由于没有名称为test的任务,因此会出现"Unsolved Reference:Test"错误.

类似地,finalizedBy(tasks.jacocoTestReport)是一种指定任务依赖关系的方法,即jacocoTestReport任务应该始终在test任务之后运行.然而,由于Android项目中没有test个任务,这会导致"Unresolved reference: finalizedBy"错误.


在"How do I add plugins to subprojects based on what plugins are present?"之后,您可能需要在根build.gradle.kts中创建一个Jacoco设置,以便为使用Android插件的每个模块自动应用正确的Jacoco设置.

使用Gradle DLS script:

import org.gradle.testing.jacoco.tasks.JacocoReport

plugins {
    // your existing plugins...

    id("jacoco")
}

// rest of your configurations...

subprojects { subproject ->
    subproject.plugins.withId(Dependencies.Plugins.androidApplication) {
        setupJacoco(subproject)
    }
    subproject.plugins.withId(Dependencies.Plugins.androidLibrary) {
        setupJacoco(subproject)
    }
}


fun setupJacoco(project: Project) {
    project.tasks.register("jacocoTestReport", JacocoReport::class.java) { task ->
        task.group = "Reporting"
        task.description = "Generate Jacoco coverage reports after running tests."
        task.reports {
            xml.isEnabled = true
            html.isEnabled = true
        }
        task.executionData.setFrom(
            project.fileTree(project.buildDir).apply {
                include("**/jacoco/*.exec")
            }
        )
        task.sourceDirectories.setFrom(
            project.files(
                project.extensions.getByType<SourceSetContainer>().getByName("main").allSource.srcDirs
            )
        )
        task.classDirectories.setFrom(
            project.fileTree(
                project.extensions.getByType<SourceSetContainer>().getByName("main").output.classesDirs
            )
        )
    }
}

That script will check every subproject in the build. If a subproject applies your IDs, like Dependencies.Plugins.androidApplication or Dependencies.Plugins.androidLibrary plugin, it adds Jacoco tasks for that subproject.
For each of these projects, add a jacocoTestReport task which generates the Jacoco reports.

需要注意的一点是,Android Gradle插件creates a test task for each build variant的应用程序/库模块.例如,如果您有debugrelease构建类型,Android Gradle插件将创建testDebugUnitTesttestReleaseUnitTest个任务.

这意味着,您需要运行特定的test任务,然后运行jacocoTestReport任务,如下所示:

# Do this once, after making changes to your build.gradle.kts 
./gradlew --refresh-dependencies

# Then, each time you want to generate the report
./gradlew module1:testDebugUnitTest module1:jacocoTestReport

这将为module1运行单元测试,然后生成Jacoco报告.请注意,如果您使用的是产品风格,您可能有两种以上类型的test任务(例如,testFreeDebugUnitTesttestPaidDebugUnitTest等),因此请相应地调整您的命令以适应您的项目配置.

Android相关问答推荐

滑动以更改合成中的活动

如何清除导航抽屉中以前 Select 的项目(Jetpack Compose)

Android 14(Oneui 6)中的本地推送通知行为不一致

如何在停止和销毁时更改函数中Firebase实时数据库的子项的值我试过了,但这不起作用.请使用Kotlin

try 用Jetpack Compose理解视图模型和导航

我无法在底部导航栏中正确导航-Android底部导航视图

为什么可以';我不能直接在RecyclerView.ViewHolder中访问视图ID吗?

使用lazyColumn迁移paging3的旧代码

如何在同一行中滚动自定义布局和惰性列,就好像它们是一个组件一样

当父布局的背景为浅色时,Android ProgressBar 背景 colored颜色 变为灰色

在 kotlin 中动态添加 GridView

单击 Jetpack Compose(单选)时,我无法为列表中的单个文本着色

调用时 listFiles() nullpointerexception

无法 HEAD 'https://jcenter.bintray.com/com/facebook/react/react-native/maven-metadata.xml'

Jetpack Compose:SpanStyle 的 TextAlign(垂直居中)

如何在 compose 中使用 BottomSheetScaffold 为底页设置半展开高度?

无法为:app@debug/compileClasspath解析依赖项com.github.dhaval2404:imagepicker-support:1.7.1

在 Room 中创建一对多关系时,@Relation 类是什么意思?

在 jetpack compose 中使用 .shadow 和 Button 会导致问题

关于launchWhenX和repeatOnLifecycle的问题