我有一个有 4 个变体的 Android 应用程序,并且我有一个运行此命令的 Bitrise 实例:
./gradlew "testDevADebugUnitTestCoverage" "testDevBDebugUnitTest" "testDevCDebugUnitTest" "testDevCDebugUnitTest" "--continue" "-PjacocoEnabled=true"
在开发分支中确保一切正常。
我最近使用 Android Studio 中的 AGP 升级助手升级到 Gradle 8 和 AGP 8.0.1,当我在本地或在 Bitrise 中运行上述命令时,遇到了如下所示的几个错误。
我不得不说,Gradle 错误适用于许多不同类型的任务:
KotlinCompile
、JacocoReport
、MergeSourceSetFolders
、ProcessTestManifest
。
Some problems were found with the configuration of task ':domain:compileDevADebugKotlin' (type 'KotlinCompile').
- Gradle detected a problem with the following location: '/Users/MyUser/Developer/yapp/domain/build/tmp/kotlin-classes/devADebug'.
Reason: Task ':domain:testDevBDebugUnitTestCoverage' uses this output of task ':domain:compileDevADebugKotlin' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
Possible solutions:
1. Declare task ':domain:compileDevADebugKotlin' as an input of ':domain:testDevBDebugUnitTestCoverage'.
2. Declare an explicit dependency on ':domain:compileDevADebugKotlin' from ':domain:testDevBDebugUnitTestCoverage' using Task#dependsOn.
3. Declare an explicit dependency on ':domain:compileDevADebugKotlin' from ':domain:testDevBDebugUnitTestCoverage' using Task#mustRunAfter.
Please refer to https://docs.gradle.org/8.0.2/userguide/validation_problems.html#implicit_dependency for more details about this problem.
我尝试将 Jacoco 更新到最新版本(0.8.10),但问题仍然存在(但我什至不确定这是 Jacoco 问题)。
如何解决这个问题?我一直在寻找,但没有找到任何解决方案。
这是我的
jacoco.gradle
文件:
apply plugin: 'jacoco'
apply from: "$project.rootDir/test_coverage_excludes.gradle"
jacoco {
toolVersion = libs.versions.jacocoVersion.get()
reportsDir = file("$buildDir/reports/jacoco")
}
android {
testOptions {
unitTests.all {
jacoco {
// Required for tests ran with RobolectricTestRunner to be included in coverage
includeNoLocationClasses = true
// Required for execution using Java 11
excludes = ['jdk.internal.*']
}
}
}
}
project.afterEvaluate {
def variants
if (android.hasProperty('applicationVariants')) {
variants = android.applicationVariants.collect { it.name }
} else {
variants = android.libraryVariants.collect { it.name }
}
variants = variants.findAll { it.endsWith("Debug") || it.endsWith("debug") }
// Generate a coverage report for each variant
variants.each { variantName ->
def unitTestTaskName = "test${variantName.capitalize()}UnitTest"
def coverageTaskName = "${unitTestTaskName}Coverage"
// Create the coverage tasks
task(coverageTaskName, type: JacocoReport, dependsOn: "$unitTestTaskName") {
group = "Reporting"
description "Generate coverage reports for ${variantName.capitalize()}."
// Location of Kotlin classes
def kotlinClassDirectory = "$buildDir/tmp/kotlin-classes/$variantName"
def kotlinClassTree = fileTree(dir: kotlinClassDirectory, excludes: fileFilter)
getClassDirectories().setFrom(files([kotlinClassTree]))
// Location of the actual source
def coverageSourceDirs = [
"src/main/java",
"src/$variantName/java"
]
getAdditionalSourceDirs().setFrom(coverageSourceDirs)
getSourceDirectories().setFrom(coverageSourceDirs)
// Include both unit test and instrumentation test execution data
executionData.setFrom(fileTree(dir: buildDir, includes: ['**/*.exec', '**/*.ec']))
reports {
xml.getRequired().set(true)
html.getRequired().set(true)
csv.getRequired().set(false)
}
}
}
}
executionData
需要作为具体文件的依赖项传递。在您的配置中,报告任务依赖于构建目录中的任意文件,并且 gradle 被抱怨添加对所有任务的依赖关系,而我们只需要 unitTestTaskName
任务 的结果
executionData = tasks."$unitTestTaskName".outputs.files.filter { it.name.endsWith(".exec") }
这种方式任务仅依赖于“测试”任务生成的文件,并且 gradle 认为只需要完成这一项任务。