We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近为基于 Egg.js 的项目编写单元测试用例。写得七七八八后,想了解一下单元测试的覆盖率。由于第一次接触测试覆盖率报告,对其中一些细节存在疑惑。
经查阅资料后,整理出这篇文章,希望能解答大家一些关于测试覆盖率报告的疑问。
注:以下内容是基于 Istanbul 覆盖率引擎。不同覆盖率引擎可能会存在一些差异。
通过 Istanbul 得到的测试覆盖率报告
四个测量维度
理解以上四个测量维度并没什么大问题,但还是有些细节可以深究。
“行覆盖率”中的行是指可执行代码行(Lines of Executable Code),而不是源文件中所有的行(含空行)——(Lines of Source Code)。
可执行代码行:
一般来说,包含语句的每一行都应被视为可执行行。而复合语句(简称为语句块,用 {} 括起来)会被忽略(但其内容除外)。
注:对于可执行行的定义,不同覆盖率引擎可能会存在一些差异。
因此:
function doTheThing () // +0 { // +0 const num = 1; // +1 console.log(num); // +1 } // +0
具体以下东西会被忽略(即视为非可执行行,+0):
一些覆盖率引擎会将以下两点视为可执行行,而 Istanbul 会忽略它们:
import { isEqual } from 'lodash'; // +0 const path = require('path'); // +1 require('jquery') // +1 let filePath // +0 const fileName = 'a.txt'; // +1 注:不仅是声明,还有赋值 class Person { // +0 constructor (name) { // +0 this.name = name; // +1 } // +0 static sayHello () { // +0 console.log('hello'); // +1 } // +0 walk () {} // +0 } // +0 function doTheThing () // +0 { // +0 const num = 1; // +1 console.log(num); // +1 } // +0
import、声明都被视为非可执行行(+0),require、赋值等语句视为可执行行(+1)
如果某行存在可执行代码,则这一整行会被视为可执行代码行。
而如果一个语句被拆分为多行,则该可执行代码块中,仅第一行被会视为可执行行。
'use strict'; for // +1 ( // +0 let i=0; // +1 i < 10; // +0 i++ // +0 ) // +0 { // +0 } // +0 console.log({ // +1 a: 1, // +0 b: 2, // +0 }) // +0 function func () { // +0 return { // +1 a: 1, // +0 b: 2, // +0 } // +0 } // +0
另外,不管嵌套语句横跨多少行,可执行行的数目仅会加 1。
foo(1, bar()); // +1 foo(1, // +1 bar()); // +0
细心的读者可能会发现,注释 // +1 的那些行,其左侧都是 Nx 或粉色色块(即这两者与底色——灰色不同)。所以 可以不管以上那些概念,通过颜色的不同(非底色——灰色)即可看出哪些是可执行代码行:
// +1
Nx
绿色方框的是 Lines of Source Code、红色红框内与底色不同的色块是 Lines of Executable Code
关于可执行行的更多信息,可查阅:《sonarqube——Executable Lines》。
一般情况下,如果我们遵守良好的代码规范,可执行代码行和语句的表现是一致的。然而当我们将两个语句放一行时,就会得到不同的结果。
// 2 lines、2 statements const x = 1; console.log(x);
// 1 line、2 statements const x = 1; console.log(x);
左图是 2 lines、2 statements,右图是 1 line、2 statements
JavaScript 的 流程控制语句 有:
运算符:
condition ? exprIfTrue : exprIfFalse
我们需要确保流程控制的每个边界情况(即分支)都被执行(覆盖)。
测试覆盖率报告出现的标识有:
if
else if
else
代码中的某些分支可能很难,甚至无法测试。故 Istanbul 提供 注释语法,使得某些代码不计入覆盖率。
// 忽略一个 else 分支 /* istanbul ignore else */ if (foo.hasOwnProperty('bar')) { // do something }
// 忽略一个 if 分支 /* istanbul ignore if */ if (hardToReproduceError)) { return callback(hardToReproduceError); }
// 忽略默认值 {} var object = parameter || /* istanbul ignore next */ {};
通过注释语法,将 funB 的 if 分支排除。故 Branches 由 2/4 变为 2/3,即总分支数由 4 减为 3。
关于 Istanbul 注释语法的更多信息,请查阅《Ignoring code for coverage purposes》。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
最近为基于 Egg.js 的项目编写单元测试用例。写得七七八八后,想了解一下单元测试的覆盖率。由于第一次接触测试覆盖率报告,对其中一些细节存在疑惑。
经查阅资料后,整理出这篇文章,希望能解答大家一些关于测试覆盖率报告的疑问。
通过 Istanbul 得到的测试覆盖率报告
四个测量维度
四个测量维度
理解以上四个测量维度并没什么大问题,但还是有些细节可以深究。
行(Lines of Source Code) vs 可执行代码行(Lines of Executable Code)
“行覆盖率”中的行是指可执行代码行(Lines of Executable Code),而不是源文件中所有的行(含空行)——(Lines of Source Code)。
可执行代码行:
一般来说,包含语句的每一行都应被视为可执行行。而复合语句(简称为语句块,用 {} 括起来)会被忽略(但其内容除外)。
因此:
具体以下东西会被忽略(即视为非可执行行,+0):
非语句
一些覆盖率引擎会将以下两点视为可执行行,而 Istanbul 会忽略它们:
import、声明
import、声明都被视为非可执行行(+0),require、赋值等语句视为可执行行(+1)
如果某行存在可执行代码,则这一整行会被视为可执行代码行。
而如果一个语句被拆分为多行,则该可执行代码块中,仅第一行被会视为可执行行。
因此:
另外,不管嵌套语句横跨多少行,可执行行的数目仅会加 1。
细心的读者可能会发现,注释
// +1
的那些行,其左侧都是Nx
或粉色色块(即这两者与底色——灰色不同)。所以可以不管以上那些概念,通过颜色的不同(非底色——灰色)即可看出哪些是可执行代码行:
绿色方框的是 Lines of Source Code、红色红框内与底色不同的色块是 Lines of Executable Code
关于可执行行的更多信息,可查阅:《sonarqube——Executable Lines》。
可执行代码行 vs 语句
一般情况下,如果我们遵守良好的代码规范,可执行代码行和语句的表现是一致的。然而当我们将两个语句放一行时,就会得到不同的结果。
左图是 2 lines、2 statements,右图是 1 line、2 statements
流程控制
JavaScript 的 流程控制语句 有:
运算符:
condition ? exprIfTrue : exprIfFalse
)我们需要确保流程控制的每个边界情况(即分支)都被执行(覆盖)。
其他标识
测试覆盖率报告出现的标识有:
if
(含else if
)分支已测试,而else
分支未测试。if
(含else if
) 分支未测试。通过注释语法忽略指定代码
代码中的某些分支可能很难,甚至无法测试。故 Istanbul 提供 注释语法,使得某些代码不计入覆盖率。
通过注释语法,将 funB 的 if 分支排除。故 Branches 由 2/4 变为 2/3,即总分支数由 4 减为 3。
关于 Istanbul 注释语法的更多信息,请查阅《Ignoring code for coverage purposes》。
参考资料
The text was updated successfully, but these errors were encountered: