Eclemma说4个分支中有1个未被覆盖,但它是哪个分支?

tor*_*tor 22 java eclipse code-coverage eclemma

有没有一种简单的方法来判断我错过哪个分支?即我有一些像这样的代码:

if (x || y) {
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

在报道中突出显示Eclipse中有一个黄点表示:

错过了4个分支中的1个

但我想知道哪个分支缺失.

Mar*_*oun 17

什么可以xy是?

  • true || true真的(由于JVM优化没有涵盖:如果第一个条件是true,第二个将不会由于短路评估而评估)
  • false || true真的
  • true || false真的
  • false || false假的

  • 不应该是真正的|| 没有涵盖的真实案例? (7认同)
  • “由于 JVM 优化而未涵盖”的说法不太正确。这不是一种优化:它是在“||”运算符的语言规范中,如果第一个操作数的计算结果为 true,则不得计算第二个操作数。它是硬功能需求,而不是优化,并且是在 Java 语言而不是 JVM 中定义的。 (2认同)
  • 而且......实际上,鉴于当第一个操作数为“true”时它不能评估第二个操作数,它如何区分“true ||” true` 和 `true || 假`?我不明白如何区分“y=true”和“y=false”!我认为只有 3 种情况:“true”、“false||true”和“false||false” - 你觉得怎么样?这闻起来像是覆盖工具中的错误......! (2认同)

Bol*_*enk 14

有一个非常简单的解决方法 - 只需将每个逻辑谓词放在单独的行上,如下所示:

if (x 
    || y) {
    System.out.println("BRANCH: " + x + ", " + y);
    // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

现在,当您运行分析时,标记应直接指向遗漏的分支。添加覆盖率后,您可以以正确的方式重新格式化代码。


use*_*389 9

一个开放的问题上github上回购了Eclemma的母公司,jacoco,表明这样的功能实际上是有点难以包括.

然而,即使没有Eclemma功能,如果目标只是找出在特定情况下错过的分支,您可以检测代码以跟踪.最简单的例子是旧式的印刷语句:

if (x || y) {
    System.out.println("BRANCH: " + x + ", " + y);
    // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

然后查看输出并查看实际命中的分支(例如java ... | grep "BRANCH:" | sort | uniq).(我知道,这并不十分令人满意.)


Bre*_*yke 5

答案true|| true没有涵盖。

这是因为一旦JVM发现第一个条件为真,就不会运行第二个条件(已优化),这意味着该代码部分永远不会运行。

正如Maroun所说,4个分支中有3个将允许有条件通过。如果您仍然担心代码覆盖率,可以将条件重构为a &&而不是a ||

(x || y)与相同(!(!x && !y)),这将允许您测试所有条件,因为现在只有三个分支。

条件的原始形式经常出现在警卫声明中:

if (obj == null || obj.hasError())
{
    throw new RuntimeException();
}
Run Code Online (Sandbox Code Playgroud)

这将永远不允许您检查objis 是否为nullAND且有错误,因为它将引发Null Pointer Exception。

如果代码覆盖率很重要,则只需使用以下形式:

if (!(obj != null && !obj.hasError()))
{
    throw new RuntimeException();
}
Run Code Online (Sandbox Code Playgroud)

  • @BrettPyke如果将(x || y)转换为!(!x &&!y),则会遇到与表达式!(false && false)收敛的相同快捷问题。 (6认同)