JaCoCo 覆盖率报告(针对 Kolin)中检测到的 `encode()` 函数是什么?

What is `encode()` function detected in JaCoCo coverage report (for Kolin)?

最近我将 gradle 从 6.5.1 升级到 7.0,即

distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip

升级后,我发现我的测试覆盖率下降了。

经过调查,我发现在 Gradle 6.5.1 中,我的 JaCoCo 测试覆盖率报告显示我的一些 class 有一个 encode() 函数,但它不再存在在 Gradle 7.0.

下面我挖出了最简单的例子。代码如下

在 Gradle 6.5 中,我的 JaCoCo 报告如下(注意还有一个额外的 encode() 函数。

然而,在 Gradle 7.0 中,我的 JaCoCo 报告如下

由于缺少覆盖功能,因此我的覆盖范围下降了。尽管如此,在 Gradle 7.0 中看起来更正确,因为我的真实代码没有 encode().

我只是想了解 encode() 函数最初在哪里,为什么它不再出现在 Gradle 7.0 中?我假设 Gradle 7.0 结果正确吗?

您似乎在使用 kotlinx.Serialization。

这会为您的对象生成一些 encodeToString 和类似函数。我想 Gradle 7 现在会忽略那些?

不同版本的 Gradle 具有不同的 jacoco.toolVersion 值,您也可以 can change in your build.gradle 控制要使用的 JaCoCo 版本。

Gradle 6.5 by default uses JaCoCo 0.8.5, and starting from Gradle 6.7 default is 0.8.6.

这里是 JaCoCo 版本的变更列表 0.8.6 - https://www.jacoco.org/jacoco/trunk/doc/changes.html


很可能您的接口 ContextData 包含具有默认实现的方法 encode

JVM 从版本 8 开始支持接口中的默认方法,但是 Kotlin 支持编译为版本 6 的字节码。为此,Kotlin 编译器对此类方法做了一个技巧 - 它在实现此接口的 类 中生成方法仅将执行委托给默认实现:

以下Example.kt

interface ContextData {
  fun encode() = { /* something */ }
}

data class SearchRefinementModalOpenData(
  val userAction: String?
) : ContextData

执行

kotlin-compiler-1.4.32/bin/kotlinc Example.kt
javap -v -p SearchRefinementModalOpenData.class

显示以下字节码

public final class SearchRefinementModalOpenData implements ContextData
{
  public kotlin.jvm.functions.Function0<kotlin.Unit> encode();
    descriptor: ()Lkotlin/jvm/functions/Function0;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokestatic  #29                 // Method ContextData$DefaultImpls.encode:(LContextData;)Lkotlin/jvm/functions/Function0;
         4: areturn

JaCoCo starting from version 0.8.6 filters out such methods 因为它们是编译器工件,没有出现在原始源代码中。