为什么Istanbul / tap代码覆盖率会报告每个条件路径被覆盖时未涵盖的switch语句?

时间:2018-04-03 09:45:20

标签: javascript node.js code-coverage istanbul

在node.js应用程序中,我有一个带有getter的类,该getter包含一个大的switch语句,与此相同但更大的未使用产品特定值而不是a,b,c,1,2,3等:

Class SomeClass () {
  constructor (someVar) {
    this.someProp = someVar
  }
  get someGetter () {
    switch (this.someProp) {
      case 'a':
      case 'b':
        return 1

      case 'c':
      case 'd':
      case 'e':
        return 2

      case 'f':
        return 3

      case undefined:
        return null

      default:
        return 0
    }
  }
}

然后我有一个这样的测试用例,它到达每个可能的路径:

const expectedResults = new Map(Object.entries({
  a: 1,
  c: 2,
  f: 3,
  null: null,
  z: 0
}))

for (const [testCase, expected] of expectedResults) {
  const someInstance = new SomeClass(testCase)
  t.equal(someInstance.someGetter, expected)
}

t.end()

这使我能够覆盖node tap覆盖率报告中所有可能的路径和红色标记。

悬停,我得到一条(黄色)未覆盖的行,这是switch语句本身的行:示例代码中的第6行,行:

switch (this.someProp) {

我尝试在每个break之后添加冗余return,但这些(正确!)标记为未覆盖(因为它们无法访问)。

我想也许它在抱怨,因为它在同一路径中返回'a'但不是1的路径中测试了'b'。但如果那是问题,我不明白为什么它会标记switch语句本身,而不是那些特定的行。

1 个答案:

答案 0 :(得分:0)

当我的测试涵盖了所有可能的case:时,未覆盖的行通知消失了,而不仅仅是每条路径。

由于我的真实世界代码中存在很多很多情况,并且所有返回路径都被测试为正确,而不是大量扩展expectedResults映射,我创建了另一个更简单的测试条件每个案例的简单数组,只需确保每个案例都被识别(没有回到默认值)。像:

const allCases = ['a', 'b', 'c', 'd', 'e', 'f']

for (const testCase of allCases) {
  const someInstance = new SomeClass(testCase)
  t.notEqual(someInstance.someGetter, 0)
}

通过与默认回退值进行比较,此测试至少有一些值,它不仅仅是满足100%覆盖率:它确保交换机中的任何可能情况都不会在将来被删除等(例如,如果switch语句重新排序或修改。)