有没有一种简单的方法可以告诉我缺少哪个分支?即我有一些这样的代码:
if (x || y) {
// do stuff
}
在突出显示的报道中,Eclipse 中有一个黄点,上面写着:
错过了 4 个分支中的 1 个
但我想知道缺少哪个分支。
有没有一种简单的方法可以告诉我缺少哪个分支?即我有一些这样的代码:
if (x || y) {
// do stuff
}
在突出显示的报道中,Eclipse 中有一个黄点,上面写着:
错过了 4 个分支中的 1 个
但我想知道缺少哪个分支。
可以x
和y
是什么?
true || true
为真(由于 JVM 优化而未涵盖:如果第一个条件为true
,则由于短路评估而不会评估第二个条件)false || true
是真的true || false
是真的false || false
是假的有一个非常简单的解决方法 - 只需将每个逻辑谓词放在单独的行上,如下所示:
if (x
|| y) {
System.out.println("BRANCH: " + x + ", " + y);
// Do stuff
}
现在,当您运行分析时,标记应直接指向丢失的分支。添加覆盖率后,您可以以正确的方式重新格式化您的代码。
Eclemma 的父母 jacoco 的 github 存储库上的一个未解决问题表明,这样的功能实际上有点难以包含。
但是,即使没有 Eclemma 功能,如果目标只是找出在特定情况下遗漏的分支,您也可以检测代码以进行跟踪。最简单的例子是老式的打印语句:
if (x || y) {
System.out.println("BRANCH: " + x + ", " + y);
// Do stuff
}
然后查看输出并查看您实际点击了哪些分支(例如java ... | grep "BRANCH:" | sort | uniq
)。(我知道,不是很令人满意。)
答案是true|| true
没有被覆盖。
这是因为一旦 JVM 发现第一个条件为真,它就不会运行第二个条件(已优化),这意味着这部分代码永远不会运行。
正如 Maroun 所说,4 个分支中有 3 个将允许条件通过。如果您仍然担心代码覆盖率,您可以将条件重构为 a&&
而不是 a ||
。
(x || y)
相同(!(!x && !y))
,这将允许您测试所有条件,因为现在只有三个分支。
条件的原始形式经常出现在保护语句中:
if (obj == null || obj.hasError())
{
throw new RuntimeException();
}
这将永远不允许您检查obj
is null
AND 是否有错误,因为它会抛出空指针异常。
如果代码覆盖率很重要,那么只需使用这种形式:
if (!(obj != null && !obj.hasError()))
{
throw new RuntimeException();
}
块内的嵌套语句if
或扩展您的x
或y
谓词的语句可能存在隐式分支。
阅读: http ://emma.sourceforge.net/faq.html#q.fractional.examples
以下表达式的结果是什么?
true || true
是真的 true || false
是真的false || true
是真的false || false
是假的如果您在第一种和第二种情况下注意到第一个参数为TRUE,则无需检查第二个参数。
true && true
是真的 true && false
是假的false && true
是假的false && false
是假的或者,如果您看到使用AND运算符的场景,如果第一个参数为FALSE ,则您永远不需要检查第二个参数。
因此,您永远无法检查 4 个分支中的 1 个分支。
为了获得全面覆盖,避免编译器的隐式选择,您必须将 if 语句重写为两个
if (x) {
// do stuff
} else if (y) {
// do the same stuff
}
这将得到全面覆盖,但会被正确标记为冗余代码。看到问题后,我宁愿忍受黄线,也不愿将这种混乱的结构添加到代码中。