当前位置: 首页 > 知识库问答 >
问题:

Kotlin协程的错误Jacoco代码覆盖率

陶睿
2023-03-14

我使用Jacoco进行单元测试代码覆盖。Jacoco生成的报告显示,在我的Kotlin代码中很少遗漏分支。我注意到,根据Jacoco的说法,协程代码和它之后的代码没有被适当地覆盖。我不确定这是因为协程还是其他原因。在用IntelliJ代码覆盖率运行我的单元测试时,我的Kotlin类显示了100%的覆盖率。

我不知道为什么Jacoco显示的覆盖率较低。我已经使用Spock(Groovy)编写了单元测试。

请参考以下图片:

共有2个答案

羊舌承
2023-03-14

Jacoco版本0.8.3修复了它,它已于昨天1月24日发布。

可在此处找到完整的更新日志:https://github.com/jacoco/jacoco/releases

姬宝
2023-03-14

类似于“为什么JaCoCo不涵盖我的字符串开关语句?”:

JaCoCo执行字节码分析,而不是源代码分析。使用< code>kotlinc 1.3.10编译< code>Example.kt

package example

fun main(args: Array<String>) {
    kotlinx.coroutines.runBlocking { // line 4
    }
}

结果在两个文件中 示例kt.class示例Kt$main$1.class,最后一个字节码 (javap -v -p 示例Kit$main$1.class) 包含方法调用Suspend(Object)

  public final java.lang.Object invokeSuspend(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_FINAL
    Code:
      stack=3, locals=4, args_size=2
         0: invokestatic  #29                 // Method kotlin/coroutines/intrinsics/IntrinsicsKt.getCOROUTINE_SUSPENDED:()Ljava/lang/Object;
         3: astore_3
         4: aload_0
         5: getfield      #33                 // Field label:I
         8: tableswitch   { // 0 to 0
                       0: 28
                 default: 53
            }
        28: aload_1
        29: dup
        30: instanceof    #35                 // class kotlin/Result$Failure
        33: ifeq          43
        36: checkcast     #35                 // class kotlin/Result$Failure
        39: getfield      #39                 // Field kotlin/Result$Failure.exception:Ljava/lang/Throwable;
        42: athrow
        43: pop
        44: aload_0
        45: getfield      #41                 // Field p$:Lkotlinx/coroutines/CoroutineScope;
        48: astore_2
        49: getstatic     #47                 // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
        52: areturn
        53: new           #49                 // class java/lang/IllegalStateException
        56: dup
        57: ldc           #51                 // String call to 'resume' before 'invoke' with coroutine
        59: invokespecial #55                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
        62: athrow
      LineNumberTable:
        line 4: 3
        line 5: 49

它与源文件的第 4 行相关联,并包含分支(ifeq表交换机)。

虽然最新的JaCoCo版本(0.8.2)为各种编译器生成的工件(如switch语句中的String)提供了过滤器,但静态编程语言编译器为协程生成的字节码没有被过滤。变更日志可以在https://www.jacoco.org/jacoco/trunk/doc/changes.html中看到。https://www.jacoco.org/research/index.html还有关于字节码模式匹配的演示,显示/解释了许多编译器生成的工件。

你在IntelliJ IDEA中看到的100%-只是线路覆盖率,所以你试图比较两个完全不同的东西。作为证明 - 这是 IntelliJ IDEA 的屏幕截图,它显示了 100% 的线路覆盖率,但只执行了 if 的一个分支(其中 args.size

这里是执行相同源文件的JaCoCo报告的相应截图

上升到包级别,您可以看到 100% 的线路覆盖率,但 50% 的分支覆盖率

然后通过第一个链接< code > example kt . main . new function 2(){...}您可以再次看到方法< code > invokesuppend(Object)贡献了丢失的分支

JaCoCo版本0.8.3具有由Kotlin编译器添加的用于挂起lambdas和函数的分支过滤器:

 类似资料:
  • 我的代码运行在具有单独JVM的单独虚拟机上。我想在此虚拟机上以tcpserver模式设置JaCoCo代理以收集覆盖率数据。然后,我将在我的maven项目中以tcpclient模式设置JaCoCo代理,以连接到上面提到的VM并获取覆盖率数据。 问题是代理不收集任何覆盖数据。在中创建了覆盖率数据文件,但该文件为空。 下面是代理选项:-Java agent:/usr/xx/plugins/org . j

  • 我在声纳中的代码覆盖率显示为0%,这不是真的,因为我有单元测试。 格拉德尔 当我打开inside然后我可以看到成功的单元测试。 我在Jenkins环境中运行作为

  • 我正在尝试使用JaCoCo-javaagent传递VM参数来获得代码覆盖率 -Java agent:/test/jaco co/jaco agent . jar = dest file =/test/jaco co/jaco co . exec,includes=com。*,append=true 我能在jacoco中获得一些价值。执行文件,但无法获取覆盖率报告。我怎样才能把jacoco转化成。执

  • 我执行Jacoco单元测试代码覆盖,它显示了单元测试中需要覆盖的所有代码。 如何避免测试覆盖显示ui代码,比如onCreate()、onAttach()中的代码(fragment)。我不想要视图的代码覆盖率,但jacoco也给出了这一点。我有办法消除它吗?

  • 我正在尝试生成Jacoco代码覆盖率报告。我已经将AndroidTestCase用于我的测试类。 在过去几天里,我已经关注了堆栈溢出的各种公认答案。结果是否定的。 我的分级文件:

  • 我试图找到这个答案,但几乎找不到。我正在进行API测试,在此过程中,我需要从本地计算机调用其余的API。本地机器包含maven项目和调用相应rest API的框架。 我需要检查远程Rest API的代码覆盖率,并根据代码覆盖率形成报告。请帮忙,怎么做? 注意:我发现这个链接很有用,但是它没有详细说明该怎么做? http://eclemma.org/jacoco/trunk/doc/agent.ht