品质保证:发布覆盖率测试报告#
代码覆盖率才是评价一个项目品质的标准。在挑选一个项目的时候,有经验的使用者都会根据代码覆盖率来确定代码的可靠性。

虽然自动化测试工具可以自动验证代码的正确性,但是如果只有部分代码经过了测试,或者只是简单地跑通了代码,也不能说是一个合格的代码。比如组件库只测试一部分的组件,或者每个组件只测试了默认设置。譬如,按钮中某个属性或者某几个属性间的排列组合并没有得到测试,这样的测试还不能保证组件库的功能完全正确。
那么如何来客观评价这个测试的完备程度呢?答案就是代码覆盖率。
覆盖率概念#
代码覆盖率(Code coverage)是软件测试中的一种度量指标,描述测试过程中(运行时)被执行的源代码占全部源代码的比例。
覆盖率指标种类#
只是简单地做到行级覆盖还远远不够,可以看看下面的例子。
function getName(a, b) {
if(a && b) {
return 'Jane'
}else {
return 'Tony'
}
}以上代码只需要两个 Case,就可以将所有语句都跑一遍:
Case01: a = true ; b = true; 期待:Jane
Case02: a =false ; b= true; 期待:Tony
但是,显然这样测试甚至不能确定代码中 b 是否参与条件判断。比如下面代码可能也会出现相同的结果。
function getName(a, b) {
if(a) {
return 'Jane'
}else {
return 'Tony'
}
}所以假设覆盖率只有简单的代码行覆盖还远远不够。
在软件工程理论中会把覆盖率分为:
语句覆盖(statement coverage)
判定覆盖(decision coverage)
条件覆盖(condition coverage)
条件判定组合覆盖(condition decision coverage)
路径覆盖(path coverage)
多条件覆盖(multi-condition coverage)
修正条件判定覆盖(modified condition / decision coverage)
覆盖深度的提高显然会让代码功能验证更加全面,但是相应的实施成本也会明显提高。
理论的覆盖虽然全面但是实际生产很多指标的指导价值并不是很大。在实际生产中会将它进行简化。
在Javascript语言中,代码覆盖率通常会分为四级覆盖。
Function coverage 函数覆盖 - 每个函数是否被执行;
Line coverage 行覆盖 – 每行是否被执行;
Statement coverage 语句覆盖 - 每个语句是否被执行;
Branch coverage 分支覆盖 - 每个 if 节点是否都被执行。
这是结合了函数式语言的特点和指标的实用程度的经验之谈,也是 JavaScript 世界比较受认可的标准。
用户故事(UserStory)#
为组件库发布覆盖率报告,使测试覆盖率可视化。
任务分解(Task)#
生成覆盖率报告;
将覆盖率报告任务加入到 CI;
上传覆盖率展示平台 Codecov;
获取覆盖率徽章。
Istanbul 代码覆盖率工具#
代码覆盖率需要专用的工具生成。在 JavaScript 程序中的代码覆盖率通常都是通过 Istanbul 生成的。Istanbul 的来历是伊斯坦布尔的地毯,覆盖率报告其实就是用颜色来表示代码的运行情况,好像给代码铺上了地毯。

我们熟悉的 Jest 和组件库使用的 Vitest 测试框架,都是使用的 Istanbul。Istanbul 的实现原理是通过编译期代码插桩方式实现的。有兴趣的同学可以研究一下。咱们这里面只讲如何使用。
生成覆盖率报告#
在 Vitest 只需要在命令行中添加参数 –coverage 就可以生成覆盖率报告了。
package.json
"scripts": {
"coverage": "vitest run --coverage"
},
默认报告形式是一个静态网站。
如果想对报告进行进一步调整,可以在 vite.config.ts 中进行。
test: {
coverage: {
provider: "istanbul", // or 'c8',
reporter: ["text", "json", "html"],
},
},我调整的两项是:
指定覆盖率引擎 istanbul;
指定输出格式,默认是没有 json 格式的。这个和后面的覆盖率展示有关,务必要加。
公布覆盖率报告#
覆盖率报告放在本地只能给自己的单元测试提供依据,更大的用途在于将覆盖率报告公布展示出来,让使用者可以看到。通常会选用覆盖率展示平台,常用的有 Codecov 和 Coveralls。
Codecov 是一个开源的测试结果展示平台,将测试结果可视化。Github 上许多开源项目都使用了 Codecov 来展示单测结果。Codecov 跟 Travis CI 一样都支持 Github 账号登录,同样会同步 Github 中的项目。

还会自动的生成徽章。这个徽章是会根据报告结果动态变化的,属于客观的第三方数据,具有公信力。

首先需要登录 Codecov 网站。

一定要使用 Github 账号进行登录**,**这样它可以直接读取你的 Github 中的项目。


然后是添加访问授权,如果你的项目在你名下的组织下,也需要访问授权。

这时候你就可以在网站上找到所有 Github 中的项目。选择 【Not yet setup 】,选择需要展示覆盖率报告的网站后的【 setup repo】链接,就可以看到安装指南。

它这个安装指南是针对所有语言项目的。这里面我们只需要得到它的上传 Token 就好了。
持续集成自动更新覆盖率报告#
覆盖率报告最好能够自动按照最新版本持续更新,而不是自己手动上传。所以这个时候就需要使用 CI 工具来帮忙了。首先需要编写一个 Action。
.github/wokflows/codecov.yml
# .github/workflows/main.yml
# This is a basic workflow to help you get started with Actions
name: Code Coverage
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [main]
pull_request:
branches: [main]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
CodeCov:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- uses: pnpm/action-setup@v2.1.0
with:
version: 7.2.1
- name: Install modules
run: pnpm install
- name: Run Test Coverage
run: cd packages/smarty-ui-vite && pnpm coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
directory: packages/smarty-ui-vite/coverage
token: ${{ secrets.CODECOV_TOKEN }}上传报告环节同样使用现成的 Action 。这里面需要添加 Token,把上面 codecov 安装指南中得到的 Token 放入 Secrets 中。

提交代码就可以自动生成覆盖率报告了。

Codecov Action 会自动识别语言与测试框架的覆盖率报告种类,然后上传相应的数据。这里面要特别说明,对于 Vitest ,是上传的 json 格式的报告,所以需要确定你确实生成了 json 报告。如何生成可以看上文介绍。

添加覆盖率徽章#
最后就是富有仪式感的一步。Codecov 网站可以将测试结果生成为徽章。你可以把徽章直接放到 Github 中展示出来。
在项目的【 Settings 】中找到对应的徽章。


复盘#
这节课的主要内容是介绍覆盖率概念和发布测试覆盖率报告。
覆盖率报告是项目品质的重要指标,成熟的项目都会把项目展示在显眼的位置,大家通常都会拿代码覆盖率指标评价开源代码的成熟度。当然过高的覆盖率也会带来成本的提高,和拉低项目进步速率。
品质、进度、成本是每一个项目管理中都需要均衡的东西。所以一味追求代码覆盖率也未必是好事。这个大家要客观看待。
最后留一些思考题帮助大家复习,也欢迎在留言区讨论。
分支覆盖和行覆盖间的关系?
如何用 Codecov 完成覆盖率展示 ?
下节课,我们将给大家讲解如何使用 PullRequest,下节课见。
