JaCoCo 使用 Kotlin 和 Android 3.0 返回 0% 的覆盖率
JaCoCo returning 0% Coverage with Kotlin and Android 3.0
我正在尝试检查我用 Kotlin 编写的测试用例的代码覆盖率。当我执行 ./gradlew createDebugCoverageReport --info
时,我的 coverage.ec 文件是空的,我的报告显示我的覆盖率为 0%。请注意,测试用例是 100% 成功的。谁能想到我的 coverage.ec 文件不断返回 0 字节的任何原因?
我到处找都没有找到。
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'jacoco'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
testCoverageEnabled = true
}
release {
minifyEnabled false
testCoverageEnabled = true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:25.4.0'
testImplementation 'junit:junit:4.12'
implementation files('pathtosomejarfile')
}
jacoco {
toolVersion = "0.7.6.201602180812"
reportsDir = file("$buildDir/customJacocoReportDir")
}
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/androidTest/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: "$buildDir", includes: [
"jacoco/testDebugUnitTest.exec",
"outputs/code-coverage/connected/*coverage.ec"
])
}
几天后,我想出了解决这个问题的方法。对于那些遇到类似问题的人:
在您的 intermediates 文件夹中应该有一个 tmp 文件夹。此文件夹包含 Kotlin 文件的 .class 文件。如果您将 fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter) 的路径更改为那些 class 文件所在的位置,Jacoco 将为您生成代码覆盖率!请注意,您将无法使用此方法逐行查看覆盖范围的完整概览。
您可以通过为生成的 .class 文件定义两个不同的目录来逐行覆盖 Java 和 Kotlin 代码:
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: fileFilter)
然后,只需将两个文件树都包含在您的class目录中:
classDirectories.from = files([debugTree], [kotlinDebugTree])
尝试使用与 JaCoCo 和 IntelliJ 兼容的新 kotlinx-kover Gradle 插件。
它解决了报告为 0% 甚至更多的 inline
函数的问题。
plugins {
id("org.jetbrains.kotlinx.kover") version "0.5.0"
}
Once applied, the plugin can be used out of the box without additional configuration.
观看其YouTube announcement video and also track its roadmap from this youtrack issue。
我正在尝试检查我用 Kotlin 编写的测试用例的代码覆盖率。当我执行 ./gradlew createDebugCoverageReport --info
时,我的 coverage.ec 文件是空的,我的报告显示我的覆盖率为 0%。请注意,测试用例是 100% 成功的。谁能想到我的 coverage.ec 文件不断返回 0 字节的任何原因?
我到处找都没有找到。
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'jacoco'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
testCoverageEnabled = true
}
release {
minifyEnabled false
testCoverageEnabled = true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:25.4.0'
testImplementation 'junit:junit:4.12'
implementation files('pathtosomejarfile')
}
jacoco {
toolVersion = "0.7.6.201602180812"
reportsDir = file("$buildDir/customJacocoReportDir")
}
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/androidTest/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: "$buildDir", includes: [
"jacoco/testDebugUnitTest.exec",
"outputs/code-coverage/connected/*coverage.ec"
])
}
几天后,我想出了解决这个问题的方法。对于那些遇到类似问题的人: 在您的 intermediates 文件夹中应该有一个 tmp 文件夹。此文件夹包含 Kotlin 文件的 .class 文件。如果您将 fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter) 的路径更改为那些 class 文件所在的位置,Jacoco 将为您生成代码覆盖率!请注意,您将无法使用此方法逐行查看覆盖范围的完整概览。
您可以通过为生成的 .class 文件定义两个不同的目录来逐行覆盖 Java 和 Kotlin 代码:
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: fileFilter)
然后,只需将两个文件树都包含在您的class目录中:
classDirectories.from = files([debugTree], [kotlinDebugTree])
尝试使用与 JaCoCo 和 IntelliJ 兼容的新 kotlinx-kover Gradle 插件。
它解决了报告为 0% 甚至更多的 inline
函数的问题。
plugins {
id("org.jetbrains.kotlinx.kover") version "0.5.0"
}
Once applied, the plugin can be used out of the box without additional configuration.
观看其YouTube announcement video and also track its roadmap from this youtrack issue。