我正在使用 Jacoco 进行单元测试代码覆盖。 Jacoco生成的报告显示,在我的 Kotlin代码中,缺少很少分支。我注意到协程代码,根据Jacoco,此后的代码未正确覆盖。我不确定这是因为协程或其他原因。 使用 IntelliJ代码覆盖率运行单元测试时,我的Kotlin类显示 100%覆盖率。
我不知道为什么Jacoco的报道范围减少了。我已经使用Spock(Groovy)编写了单元测试。
请参考以下图片:
答案 0 :(得分:4)
类似于“ Why is JaCoCo not covering my String switch statements?”:
JaCoCo执行字节码分析,而不是源代码。 Example.kt
与kotlinc 1.3.10
package example
fun main(args: Array<String>) {
kotlinx.coroutines.runBlocking { // line 4
}
}
产生两个文件ExampleKt.class
和ExampleKt$main$1.class
,最后一个(javap -v -p ExampleKt$main$1.class
)的字节码包含方法invokeSuspend(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
,tableswitch
)。
尽管JaCoCo版本(0.8.2)的最新版本具有针对各种编译器生成的构件的过滤器,例如String
语句中的switch
,但未过滤Kotlin编译器为协程生成的字节码。可以在https://www.jacoco.org/jacoco/trunk/doc/changes.html上看到Changelog,在https://www.jacoco.org/research/index.html上可以看到presentation about bytecode pattern matching,它可以显示/解释许多编译器生成的工件。
您在IntelliJ IDEA中看到的是100%-仅仅是线路覆盖率,因此您正在尝试比较两个完全不同的事物。作为证明-这是IntelliJ IDEA的屏幕截图,显示了100%的行覆盖率,但是仅执行了if
的一个分支(其中args.size >= 0
的值为true
)
这是执行相同源文件的JaCoCo报告的相应屏幕截图
上升到包装级别,您可以看到100%的行覆盖率,但是看到50%的分支覆盖率
然后通过第一个链接ExampleKt.main.new Function2() {...}
进入类级别,您可以再次看到方法invokeSuspend(Object)
贡献了丢失的分支
JaCoCo version 0.8.3具有用于Kotlin编译器添加的分支的过滤器,用于暂停lambda和函数:
答案 1 :(得分:1)
Jacoco版本0.8.3对其进行了修复,它已于1月24日昨天发布。
完整的更改日志可以在这里找到:https://github.com/jacoco/jacoco/releases