什么是 JavaScript 单元测试的代码覆盖分支

Posted

技术标签:

【中文标题】什么是 JavaScript 单元测试的代码覆盖分支【英文标题】:What is a branch in code coverage for JavaScript unit testing 【发布时间】:2016-05-04 06:19:51 【问题描述】:

我使用 Istanbul 来覆盖 AngularJS 项目中单元测试的代码覆盖率。有 4 种类型的覆盖范围,它们是

声明 分支 功能 行

语句、函数和行都可以,但我不明白“分支”是什么。什么是分支?

【问题讨论】:

【参考方案1】:

分支是运行时可以选择是否采用一条路径或另一条路径的地方。举个例子:

if(a) 
    Foo();


if(b) 
    Bar();


Yay();

当到达第一行时,它可以决定是否要进入if(a)-statement 的主体。此外,它可以决定不这样做。在这个阶段,我们已经看到了两条路径(一个分支)。

之后的下一个语句变得更有趣。它可以进入if 主体并执行Bar。它也不能那样做。但请记住,我们之前已经有一个分支。如果Foo 被调用,结果可能会有所不同。

所以我们最终得到了四种可能的路径:

不打电话给Foo,也不打电话给Bar 呼叫Foo,不呼叫Bar 不调用Foo,调用Bar 同时调用FooBar

最后一个Yay 总是被执行,不管是Foo 还是Bar 被调用,所以这不算作一个分支。所以上面的代码sn-p包含四个路径/两个分支(调用Foo()与否,调用Bar()与否)。

就像已经提到的其他答案一样,有许多语句可能导致分支 (if/switch)。一些(但不是全部)包括:

条件循环(即while/for/do-whilebreakcontinue 声明 二进制短路运算符(即&&/||例如。给定foo && bar,如果foofalse,则不必评估bar。同样对于foo || bar,如果footruebar 也不必进行评估。 默认参数(即function A(someVar = []) ... 这是因为对该方法的调用被解释为if-语句。对于此方法的每次调用,都会检查参数是否为undefined。如果是,则为someVar 设置默认参数(对于上面的示例)。这会导致分支存在。

代码覆盖率工具希望确保您已经测试了所有分支。最好的情况是所有路径都经过测试,甚至所有(边缘情况)值,而不仅仅是分支。这是为了确保不会执行不需要的行为。

【讨论】:

感谢您的详细回答。 @Arseniy-II 默认参数值如何导致分支?这只是一个不同的价值/电话。不过我可能是错的。 @Caramiriel 我刚刚在测试时将其作为分支。而且我认为从开玩笑的角度来看,它与:let actualVar = someVar || [] 相同。所以基本上它是“使用[ ] IF someVarundefined”。但如果你能检查一下就好了:)【参考方案2】:

来自Wikipedia:

是否每个控制结构(例如 if 和 case 语句)的每个分支(也称为 DD 路径)都已执行?例如,给定一个 if 语句,是否同时执行了 true 和 false 分支?另一种说法是,程序中的每一条边都被执行了吗?

您必须为每个控制结构测试所有可能的情况(在 if 语句、f.e. 和 switch 的所有情况下输入/不输入)。分支覆盖率是衡量(通常以百分比表示)测试覆盖的总分支数量的指标。

【讨论】:

【参考方案3】:

代码可以采用多条路径的地方,即它的分支。分支语句的几个示例是 if/elseswitch 语句。

分支覆盖跟踪哪些分支已执行,因此您可以确保正确测试所有路由。

【讨论】:

以上是关于什么是 JavaScript 单元测试的代码覆盖分支的主要内容,如果未能解决你的问题,请参考以下文章

Karma +Jasmine+ require JS进行单元测试并生成测试报告代码覆盖率报告

为啥即使单元测试全部通过,我的代码覆盖率也为零?

web前端好帮手 - Jest单元测试工具

Angular 单元测试中业力代码覆盖率报告中的 1x 3x 等是啥意思?

如何在 IAR 中执行单元测试和代码覆盖

单元测试-代码覆盖率工具 -- JaCoCo