istanbuljs 覆盖率数据字典
概述
istanbuljs 是 JavaScript 代码覆盖率的黄金标准。本数据字典描述了覆盖率数据的主要结构和字段。
主要数据结构
1. Coverage 对象
顶级覆盖率数据结构,包含所有文件的覆盖率信息。
{
"path/to/file.js": {
// FileCoverage 对象
}
}2. FileCoverage
单个文件的完整覆盖率数据。
| 字段 | 类型 | 描述 |
|---|---|---|
path | string | 文件的绝对路径 |
statementMap | Object | 语句映射表 |
fnMap | Object | 函数映射表 |
branchMap | Object | 分支映射表 |
s | Object | 语句执行计数 |
f | Object | 函数执行计数 |
b | Object | 分支执行计数 |
3. StatementMap
描述代码中每个语句的位置信息。
| 字段 | 类型 | 描述 |
|---|---|---|
start | Location | 语句开始位置 |
end | Location | 语句结束位置 |
4. FunctionMap
描述代码中每个函数的信息。
| 字段 | 类型 | 描述 |
|---|---|---|
name | string | 函数名称(匿名函数为 “(anonymous_N)“) |
decl | Location | 函数声明位置 |
loc | Location | 函数体位置 |
line | number | 函数声明行号 |
5. BranchMap
描述代码中每个分支的信息。
| 字段 | 类型 | 描述 |
|---|---|---|
loc | Location | 分支位置 |
type | string | 分支类型 (if, switch, cond-expr, binary-expr) |
locations | Array<Location> | 分支条件的所有可能位置 |
6. Location
描述源代码中的一个位置。
| 字段 | 类型 | 描述 |
|---|---|---|
start | Position | 开始位置 |
end | Position | 结束位置 |
7. Position
源代码中的具体坐标。
| 字段 | 类型 | 描述 |
|---|---|---|
line | number | 行号(从 1 开始) |
column | number | 列号(从 0 开始) |
计数器对象
8. 语句计数器
记录每个语句的执行次数。
{
"0": 5, // 语句 ID 0 执行了 5 次
"1": 0, // 语句 ID 1 未执行
"2": 3 // 语句 ID 2 执行了 3 次
}9. 函数计数器
记录每个函数的调用次数。
{
"0": 2, // 函数 ID 0 被调用了 2 次
"1": 0, // 函数 ID 1 未被调用
"2": 1 // 函数 ID 2 被调用了 1 次
}10. 分支计数器
记录每个分支条件的执行次数。
{
"0": [5, 2], // 分支 ID 0: 真分支 5 次,假分支 2 次
"1": [0, 3], // 分支 ID 1: 真分支 0 次,假分支 3 次
"2": [1, 1] // 分支 ID 2: 两个分支各执行 1 次
}分支类型描述
分支类型
| 类型 | 描述 | 示例 |
|---|---|---|
if | if 语句 | if (condition) { ... } |
switch | switch 语句 | switch (value) { case 1: ... } |
cond-expr | 三元运算符 | condition ? value1 : value2 |
binary-expr | 逻辑运算符 | a && b, x || y |
报告摘要数据
11. Summary
每种覆盖率类型的统计摘要。
| 字段 | 类型 | 描述 |
|---|---|---|
total | number | 总数 |
covered | number | 覆盖数 |
skipped | number | 跳过数 |
pct | number | 覆盖率百分比 |
12. Coverage Summary
文件或整体的覆盖率摘要。
| 字段 | 类型 | 描述 |
|---|---|---|
lines | Summary | 行覆盖率摘要 |
functions | Summary | 函数覆盖率摘要 |
statements | Summary | 语句覆盖率摘要 |
branches | Summary | 分支覆盖率摘要 |
实际示例
math.js 文件内容
function add(a, b) {
return a + b;
}
function subtract(a, b) {
if (a > b) {
return a - b;
} else {
return b - a;
}
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
module.exports = { add, subtract, multiply, divide };完整的FileCoverage示例
{
"path": "/project/src/math.js",
"statementMap": {
"0": {"start": {"line": 1, "column": 0}, "end": {"line": 1, "column": 25}},
"1": {"start": {"line": 2, "column": 2}, "end": {"line": 2, "column": 13}},
"2": {"start": {"line": 5, "column": 0}, "end": {"line": 5, "column": 30}},
"3": {"start": {"line": 6, "column": 2}, "end": {"line": 6, "column": 25}},
"4": {"start": {"line": 8, "column": 4}, "end": {"line": 8, "column": 15}},
"5": {"start": {"line": 10, "column": 4}, "end": {"line": 10, "column": 15}},
"6": {"start": {"line": 13, "column": 0}, "end": {"line": 13, "column": 25}},
"7": {"start": {"line": 14, "column": 2}, "end": {"line": 14, "column": 13}},
"8": {"start": {"line": 17, "column": 0}, "end": {"line": 17, "column": 30}},
"9": {"start": {"line": 18, "column": 2}, "end": {"line": 18, "column": 25}},
"10": {"start": {"line": 20, "column": 4}, "end": {"line": 20, "column": 15}},
"11": {"start": {"line": 22, "column": 4}, "end": {"line": 22, "column": 15}},
"12": {"start": {"line": 25, "column": 0}, "end": {"line": 25, "column": 25}}
},
"fnMap": {
"0": {
"name": "add",
"decl": {"start": {"line": 1, "column": 9}, "end": {"line": 1, "column": 12}},
"loc": {"start": {"line": 1, "column": 20}, "end": {"line": 3, "column": 1}},
"line": 1
},
"1": {
"name": "subtract",
"decl": {"start": {"line": 5, "column": 9}, "end": {"line": 5, "column": 17}},
"loc": {"start": {"line": 5, "column": 25}, "end": {"line": 12, "column": 1}},
"line": 5
},
"2": {
"name": "multiply",
"decl": {"start": {"line": 13, "column": 9}, "end": {"line": 13, "column": 16}},
"loc": {"start": {"line": 13, "column": 24}, "end": {"line": 15, "column": 1}},
"line": 13
},
"3": {
"name": "divide",
"decl": {"start": {"line": 17, "column": 9}, "end": {"line": 17, "column": 15}},
"loc": {"start": {"line": 17, "column": 23}, "end": {"line": 24, "column": 1}},
"line": 17
}
},
"branchMap": {
"0": {
"loc": {"start": {"line": 6, "column": 2}, "end": {"line": 6, "column": 25}},
"type": "if",
"locations": [
{"start": {"line": 6, "column": 2}, "end": {"line": 6, "column": 25}},
{"start": {"line": 6, "column": 2}, "end": {"line": 6, "column": 25}}
]
},
"1": {
"loc": {"start": {"line": 18, "column": 2}, "end": {"line": 18, "column": 25}},
"type": "if",
"locations": [
{"start": {"line": 18, "column": 2}, "end": {"line": 18, "column": 25}},
{"start": {"line": 18, "column": 2}, "end": {"line": 18, "column": 25}}
]
}
},
"s": {"0": 1, "1": 1, "2": 1, "3": 1, "4": 3, "5": 2, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1},
"f": {"0": 5, "1": 3, "2": 2, "3": 1},
"b": {"0": [3, 2], "1": [1, 0]}
}