TypeScript 代码测试覆盖率:最佳工具与指标

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript 代码测试覆盖率:如何停止猜测,开始测量

\n\n

想象一下,您正在组装一个带有许多齿轮的复杂机械。您确信一切安装正确,但一按下“启动”按钮,就传来刺耳的摩擦声,机械卡住了。似曾相识?在 TypeScript 开发的世界里,这些“机械”就是我们的应用程序。而代码测试覆盖率就像一次试组装,它告诉我们哪些零件已经检查过,哪些还听天由命。

\n\n

许多开发者对覆盖率指标持怀疑态度:“追求百分比是万恶之源”,“100% 覆盖率并不能保证没有 bug”。这确实是事实。但就像任何工具一样,代码覆盖率可以有益,也可能有害——完全取决于如何使用它。在本文中,我们将探讨如何正确测量 TypeScript 中的覆盖率,有哪些可用工具,以及如何避免让指标成为目的本身。

\n\n

什么是代码覆盖率,为什么 TypeScript 也不例外

\n\n

代码覆盖率 (code coverage) 是一项指标,显示测试执行期间运行了原始代码的哪一部分。在编译为 JavaScript 的 TypeScript 中,覆盖率测量是在编译后的代码层面进行的,但现代工具能够以原始 TS 代码的形式漂亮地显示结果。

\n\n

需要了解的主要覆盖率指标:

\n\n
    \n
  • 行覆盖率 (Line coverage) — 至少执行过一次的代码行百分比。
  • \n
  • 分支覆盖率 (Branch coverage) — 经过测试的分支(if/else、switch、三元运算符)百分比。
  • \n
  • 函数覆盖率 (Function coverage) — 被调用过的函数/方法百分比。
  • \n
  • 语句覆盖率 (Statement coverage) — 代码中单个指令(语句)的百分比。
  • \n
\n\n

对于 TypeScript 项目,分支覆盖率尤为重要,因为强类型并不能防止条件中的逻辑错误。您可以正确定义所有变量的类型,但可能会忘记数组为空而函数期望至少一个元素的情况。

\n\n

TypeScript 覆盖率测量工具

\n\n

1. Istanbul (nyc) — 覆盖率工具之祖

\n\n

Istanbul 是测量 JavaScript 和 TypeScript 代码覆盖率最流行的工具。它可以作为独立工具(通过 nyc 包)运行,也可以作为测试框架的内置模块使用。

\n\n

要在 TypeScript 项目中开始使用 Istanbul,请安装:

\n\n
npm install --save-dev nyc typescript ts-node
\n\n

创建 .nycrc 配置文件:

\n\n
{\n  "extends": "@istanbuljs/nyc-config-typescript",\n  "all": true,\n  "include": ["src/**/*.ts"],\n  "exclude": ["src/**/*.test.ts", "src/**/*.spec.ts"],\n  "reporter": ["text", "html", "lcov"],\n  "check-coverage": true,\n  "branches": 80,\n  "lines": 85,\n  "functions": 85,\n  "statements": 85\n}
\n\n

运行带覆盖率的测试:

\n\n
npx nyc mocha --require ts-node/register src/**/*.test.ts
\n\n

Istanbul 会在控制台 (text) 和 HTML 页面中生成报告,其中绿色高亮显示已覆盖的代码,红色显示未覆盖的代码。非常直观。

\n\n

2. Jest — 一站式解决方案

\n\n

Jest 是 TypeScript 最流行的测试框架。它已经包含了基于 Istanbul 的内置覆盖率工具。您无需安装任何额外内容。

\n\n

在 jest.config.ts 中的基本配置:

\n\n
import type { Config } from 'jest';\n\nconst config: Config = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n  collectCoverage: true,\n  coverageDirectory: 'coverage',\n  coverageReporters: ['text', 'html', 'lcov'],\n  collectCoverageFrom: [\n    'src/**/*.ts',\n    '!src/**/*.test.ts',\n    '!src/**/*.spec.ts',\n    '!src/types/**/*.ts'\n  ],\n  coverageThresho                

博客

书籍推荐