1. 项目概述:为什么我们需要Jest?
如果你写过JavaScript代码,尤其是稍微复杂一点的业务逻辑,那么下面这个场景你一定不陌生:你修改了一个函数,然后心惊胆战地刷新页面,祈祷它不会影响到其他看似无关的功能。或者,你重构了一段代码,结果上线后半夜被报警电话叫醒,因为某个你完全没想到的边角情况崩了。这种“牵一发而动全身”的恐惧,是每个开发者都经历过的噩梦。
测试,就是对抗这种噩梦最有效的武器。而Jest,则是当前JavaScript生态中,这把武器最趁手、最锋利的一个。它由Facebook开源并维护,最初是为了测试React应用而生,但凭借其“零配置”的理念、强大的功能和极佳的开发体验,迅速成为了整个JavaScript社区单元测试的事实标准。无论是Node.js后端服务、React/Vue前端组件,还是普通的工具库,Jest都能轻松应对。
你可能觉得写测试很麻烦,是浪费时间。但我想告诉你一个反直觉的事实: 写好测试,是提升开发效率最快的方式之一 。它带来的好处远不止“保证代码正确”这么简单:
- 即时反馈,提升信心 :你不再需要手动点击页面、输入数据来验证逻辑。写完代码,运行测试,几秒钟内就能知道它是否按预期工作。这种即时反馈能极大提升你的开发信心和节奏。
- 充当活文档 :一个好的测试用例,本身就是对函数功能和使用方法最清晰的说明。新同事接手代码,看测试比看晦涩的业务逻辑要直观得多。
- 支持安全重构 :这是测试最大的价值。当你需要优化代码结构、修复技术债务时,完备的测试套件就是你的安全网。只要所有测试都通过,你就可以确信你的改动没有破坏原有功能。
- 促进更好的设计 :为了让代码易于测试,你自然会倾向于编写职责单一、接口清晰、耦合度低的模块。这本身就是优秀软件设计的核心原则。
而Jest,将写测试的门槛降到了最低。它内置了测试运行器、断言库、Mock工具和覆盖率报告,你几乎不需要任何额外配置就能开始。它模拟了浏览器的DOM环境(通过
jsdom
),让你能在Node.js环境下测试前端代码。它的watch模式可以监听文件变化自动运行测试,体验丝滑。今天,我们就用5分钟,彻底掌握用Jest编写第一个测试用例的核心要领,让你从此告别“盲改代码”的时代。
2. 环境准备与项目初始化
在开始写测试之前,我们需要先把Jest这个工具安装到项目中,并进行最基础的配置。别担心,这个过程简单到超乎想象。
2.1 创建项目与安装Jest
首先,你需要一个Node.js项目。如果你还没有,可以随便创建一个文件夹,然后初始化它。
# 创建一个新的项目目录
mkdir my-first-jest-test
cd my-first-jest-test
# 初始化npm项目(一路回车即可)
npm init -y
现在,我们来安装Jest。Jest既可以全局安装,但更推荐作为项目的开发依赖(devDependencies)安装,这样可以保证团队每个成员和CI/CD环境都使用完全相同的版本。
# 使用npm安装
npm install --save-dev jest
# 或者使用yarn
yarn add --dev jest
安装完成后,你的
package.json
文件中会自动添加Jest的依赖。同时,我们修改一下
package.json
,添加一个运行测试的脚本命令,这会让我们后续的操作更方便。
{
"name": "my-first-jest-test",
"version": "1.0.0",
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest": "^29.7.0"
}
}
注意 :这里
scripts里的test命令,直接写jest即可。当你运行npm test或yarn test时,npm/yarn会自动去node_modules/.bin目录下找到Jest的可执行文件来运行。这是一种标准做法。
2.2 理解Jest的默认约定
Jest之所以号称“零配置”,是因为它有一套非常合理的默认约定。了解这些约定,你就能知道把测试文件放在哪里、如何命名。
-
测试文件识别
:Jest默认会查找项目中所有以
.test.js、.spec.js结尾的文件,或者放在__tests__目录下的.js文件。例如,sum.test.js或__tests__/sum.js都会被识别为测试文件。 -
测试运行
:当你执行
npm test时,Jest会自动运行所有它找到的测试文件。 -
模块系统
:Jest默认支持ES Module(
import/export)和CommonJS(require/module.exports)语法,你不需要额外配置Babel(对于较新的Node.js版本或通过配置支持)。
对于一个小型或新项目,你完全不需要创建任何配置文件,直接按照约定写测试文件就行。Jest的智能默认值已经能处理大多数情况。
2.3 编写第一个被测试的函数
测试总得有个对象。我们先创建一个非常简单的函数作为测试目标。在项目根目录下创建一个
math.js
文件:
// math.js
function sum(a, b) {
return a + b;
}
module.exports = { sum };
这个
sum
函数简单到令人发指,但它是一个完美的起点。我们接下来就要为它编写测试,验证它是否真的能正确完成加法。
3. 编写你的第一个测试用例
万事俱备,现在让我们动手编写第一个测试文件。按照Jest的约定,我们创建一个名为
math.test.js
的文件,和
math.js
放在同一目录下。
3.1 测试文件的结构与语法
打开
math.test.js
,输入以下内容:
// math.test.js
const { sum } = require('./math');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
让我们逐行拆解这个最简单的测试用例:
-
导入被测模块 :
const { sum } = require(‘./math’);-
这行代码引入了我们想要测试的
sum函数。如果你使用ES Module,可以写成import { sum } from ‘./math.js’;。
-
这行代码引入了我们想要测试的
-
test函数 :test(‘adds 1 + 2 to equal 3’, () => { … });-
这是Jest定义单个测试用例的核心函数。它接受两个参数:
- 第一个参数(字符串) :测试用例的描述。这个描述应该清晰、具体地说明这个测试在验证什么。好的描述能在测试失败时让你快速定位问题,例如“当输入为空字符串时返回默认值”。
- 第二个参数(函数) :包含实际测试逻辑的函数。Jest会执行这个函数。
-
这是Jest定义单个测试用例的核心函数。它接受两个参数:
-
expect与toBe(断言) :expect(sum(1, 2)).toBe(3);-
这是测试的灵魂——断言。它的逻辑是:“我
期望
sum(1,2)的 结果toBe(等于)3”。 -
expect():接收一个值,这个值通常是你调用被测函数得到的结果(称为“实际值”)。 -
.toBe():这是一个“匹配器”(Matcher)。它用来比较expect传入的实际值是否符合某个条件(这里条件是等于3)。Jest提供了几十个不同的匹配器来处理各种情况(是否相等、是否为真、是否包含某元素、是否抛出错误等)。
-
这是测试的灵魂——断言。它的逻辑是:“我
期望
3.2 运行测试并查看结果
现在,在终端中运行我们之前配置好的测试命令:
npm test
# 或
yarn test
你会看到类似下面的输出:
PASS ./math.test.js
✓ adds 1 + 2 to equal 3 (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.234 s
Ran all test suites.
恭喜!你的第一个测试用例通过了。Jest给出了清晰的反馈:一个绿色的对勾(✓),告诉我们测试用例“adds 1 + 2 to equal 3”通过了。下面还总结了测试套件和测试用例的通过情况。
3.3 让测试失败:理解错误报告
一个只能通过的测试不是好测试。我们故意写一个错误的断言,看看Jest如何报告失败。
修改
math.test.js
,将
toBe(3)
改为
toBe(4)
:
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(4); // 这显然是错的
});
再次运行
npm test
,你会看到红色的错误报告:
FAIL ./math.test.js
✕ adds 1 + 2 to equal 3 (3 ms)
● adds 1 + 2 to equal 3
expect(received).toBe(expected) // Object.is equality
Expected: 4
Received: 3
2 |
3 | test('adds 1 + 2 to equal 3', () => {
> 4 | expect(sum(1, 2)).toBe(4);
| ^
5 | });
6 |
at Object.<anonymous> (math.test.js:4:21)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.247 s
Ran all test suites.
这个报告非常详细:
-
✕表示测试失败。 -
●后面是失败的测试描述。 -
最关键的部分
:它清晰地指出了断言失败的原因。
Expected: 4表示你期望的值,Received: 3表示实际得到的值。一眼就能看出是哪里不对。 -
它还指出了错误发生的具体位置(
math.test.js第4行第21列),方便你快速定位。
请把断言改回正确的
toBe(3)
,我们继续。
实操心得 : 测试失败的报告和测试通过的结果同样重要,甚至更重要。 养成习惯,在编写测试时, 先故意让它失败一次 ,确保你写的断言确实在检查你想要检查的东西,并且错误信息是你能够理解的。这能有效避免“假通过”的测试(比如断言永远为真)。
4. Jest核心概念深度解析
掌握了第一个测试用例后,我们来深入了解一下Jest的几个核心概念,它们是你编写有效测试的基石。
4.1 测试套件(
describe
)组织多个测试
当你有多个相关的测试用例时,可以用
describe
函数将它们分组,形成一个测试套件。这能让你的测试结构更清晰,报告也更易读。
让我们为
math.js
添加一个
subtract
函数,并一起测试。
// math.js 更新
function sum(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = { sum, subtract };
然后更新测试文件:
// math.test.js 更新
const { sum, subtract } = require('./math');
describe('math functions', () => {
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds 5 + 7 to equal 12', () => {
expect(sum(5, 7)).toBe(12);
});
test('subtracts 5 - 3 to equal 2', () => {
expect(subtract(5, 3)).toBe(2);
});
test('subtracts 0 - 1 to equal -1', () => {
expect(subtract(0, 1)).toBe(-1);
});
});
运行测试,输出会是这样:
PASS ./math.test.js
math functions
✓ adds 1 + 2 to equal 3 (1 ms)
✓ adds 5 + 7 to equal 12
✓ subtracts 5 - 3 to equal 2
✓ subtracts 0 - 1 to equal -1
看,所有测试都被归在了“math functions”这个套件下,层次分明。
describe
可以嵌套使用,用于构建更复杂的测试结构,例如按模块或按功能分组。
4.2 常用匹配器(Matcher)一览
toBe
用于精确相等(
Object.is
),但我们需要测试各种条件。Jest提供了丰富的匹配器。
| 匹配器 | 用途 | 示例 |
|---|---|---|
toBe
| 精确相等(适用于数字、字符串、布尔值等原始类型) |
expect(1 + 1).toBe(2)
|
toEqual
| 深度递归比较对象或数组的值 (最常用) |
expect({a:1}).toEqual({a:1})
|
toBeNull
|
只匹配
null
|
expect(null).toBeNull()
|
toBeUndefined
|
只匹配
undefined
|
expect(undefined).toBeUndefined()
|
toBeDefined
|
与
toBeUndefined
相反
|
expect(‘value’).toBeDefined()
|
toBeTruthy
| 匹配任何在布尔上下文中为真的值 |
expect(1).toBeTruthy()
|
toBeFalsy
| 匹配任何在布尔上下文中为假的值 |
expect(0).toBeFalsy()
|
toBeGreaterThan
| 数字大于 |
expect(10).toBeGreaterThan(5)
|
toBeGreaterThanOrEqual
| 数字大于等于 |
expect(10).toBeGreaterThanOrEqual(10)
|
toBeLessThan
| 数字小于 |
expect(5).toBeLessThan(10)
|
toBeCloseTo
| 浮点数近似相等,避免精度问题 |
expect(0.1+0.2).toBeCloseTo(0.3)
|
toMatch
| 字符串匹配正则表达式 |
expect(‘team’).toMatch(/t.m/)
|
toContain
| 数组或可迭代对象包含某元素 |
expect([1,2,3]).toContain(2)
|
toThrow
| 函数调用时抛出错误 |
expect(()=>{throw Error()}).toThrow()
|
重点区分
toBe
和
toEqual
:
这是新手最容易混淆的地方。
toBe
检查的是
引用是否相同
(类似于
===
),对于对象和数组,即使内容一样,引用不同也会失败。而
toEqual
会递归检查每个字段的值是否相等。
const obj1 = { a: 1 };
const obj2 = { a: 1 };
const obj3 = obj1;
expect(obj1).toBe(obj3); // 通过,是同一个引用
expect(obj1).toBe(obj2); // 失败!内容相同,但不是同一个对象
expect(obj1).toEqual(obj2); // 通过,值深度相等
在测试中,
对于对象和数组,99%的情况你应该使用
toEqual
。
4.3 测试异步代码
现代JavaScript离不开异步操作。Jest提供了多种优雅的方式来测试异步代码。
1. 使用
async/await
(推荐)
这是最清晰的方式。只需在测试函数前加上
async
关键字,然后
await
异步操作即可。
假设我们有一个异步函数
fetchData
,它返回一个Promise。
// asyncFunctions.js
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => resolve('peanut butter'), 100);
});
}
module.exports = { fetchData };
测试文件:
// asyncFunctions.test.js
const { fetchData } = require('./asyncFunctions');
test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});
2. 使用
.resolves
/
.rejects
匹配器
这种方式让你可以直接在
expect
语句中处理Promise,无需
async/await
。
test('the data is peanut butter with resolves', () => {
// 注意:这里必须 return 这个 Promise,Jest会等待它解决
return expect(fetchData()).resolves.toBe('peanut butter');
});
// 测试异步错误
function fetchDataWithError() {
return Promise.reject('error');
}
test('the fetch fails with an error', () => {
return expect(fetchDataWithError()).rejects.toMatch('error');
});
注意事项 :当你测试返回Promise的函数时, 必须确保Promise被返回给Jest 。如果你使用了
async/await,Jest会自动处理。如果你直接返回一个expect(...).resolves的Promise,也必须用return。否则,Jest可能在Promise解决前就结束测试,导致测试误通过。
4.4 模拟(Mock)函数与模块
单元测试的核心是“隔离”。我们想测试函数A,但函数A内部调用了函数B。为了不让函数B的错误影响对A的测试,我们需要“模拟”函数B的行为。这就是Mock的用武之地。Jest的Mock功能极其强大。
模拟一个函数:
// 创建一个模拟函数
const mockCallback = jest.fn();
// 模拟函数可以配置返回值
mockCallback.mockReturnValueOnce(10).mockReturnValueOnce('x').mockReturnValue(true);
// 在测试中使用它
test('mock function', () => {
expect(mockCallback()).toBe(10);
expect(mockCallback()).toBe('x');
expect(mockCallback()).toBe(true);
expect(mockCallback()).toBe(true); // 之后一直返回 true
// 还可以检查模拟函数是如何被调用的
expect(mockCallback).toHaveBeenCalledTimes(4); // 被调用了4次
});
模拟整个模块:
这是更常见的场景。假设我们有一个工具模块
utils.js
,它里面有一个发送网络请求的函数
request
,我们不想在测试中真的发送请求。
// utils.js
function request() {
// 真实的网络请求,很慢且有副作用
return fetch('...');
}
module.exports = { request };
// service.js (我们要测试这个)
const { request } = require('./utils');
function getUser() {
return request().then(data => data.user);
}
module.exports = { getUser };
在测试
getUser
时,我们想模拟掉
utils.request
:
// service.test.js
// 1. 在文件顶部模拟整个 utils 模块
jest.mock('./utils');
const { getUser } = require('./service');
const { request } = require('./utils'); // 注意:这里拿到的是已经被Jest自动创建的模拟函数
test('getUser returns user data', async () => {
// 2. 设置模拟函数的返回值
request.mockResolvedValue({ user: 'John Doe' });
// 3. 执行测试
const user = await getUser();
// 4. 断言结果
expect(user).toBe('John Doe');
// 5. 断言模拟函数被正确调用
expect(request).toHaveBeenCalledTimes(1);
});
通过
jest.mock(‘./utils’)
,Jest会自动用模拟函数替换
utils
模块的所有导出。这样,
service.js
中引入的
request
就是一个我们可以控制的模拟函数,不会发出真实请求。
Mock是单元测试中高级但必备的技能,它能让你将测试目标完全隔离出来。
5. 进阶配置与最佳实践
掌握了基础用法后,一些配置和最佳实践能让你的测试更高效、更健壮。
5.1 配置文件(jest.config.js)常用选项
虽然Jest可以零配置运行,但通过配置文件可以定制化很多行为。在项目根目录创建
jest.config.js
文件。
// jest.config.js
module.exports = {
// 在每个测试文件执行之前,运行一些代码来设置测试环境(如配置jsdom)
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// 测试环境。默认为'node',测试前端代码时可设为'jsdom'以模拟浏览器环境
testEnvironment: 'jsdom',
// 告诉Jest需要匹配哪些文件
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)'
],
// 忽略某些路径
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
// 收集测试覆盖率信息
collectCoverage: true,
coverageDirectory: 'coverage',
collectCoverageFrom: [
'src/**/*.{js,jsx}',
'!src/**/*.d.ts',
'!src/index.js',
],
};
-
setupFilesAfterEnv:非常有用。你可以在这里面全局引入测试库(如@testing-library/jest-dom来扩展匹配器),或者设置一些全局的Mock。 -
testEnvironment: ‘jsdom’:如果你想测试涉及document,window等浏览器API的前端代码,这是必须的。 -
collectCoverage:开启覆盖率报告,可以直观地看到有多少代码被测试覆盖了。
5.2 测试驱动开发(TDD)快速体验
TDD是一种先写测试,再写实现代码的开发模式。它的节奏通常是“红-绿-重构”。
- 红 :写一个失败的测试。此时功能还没实现,测试自然是红的。
- 绿 :用最简单、最快速的方式编写代码,让测试通过。
- 重构 :在测试的保护下,优化代码结构,消除重复,提高可读性。
我们用TDD来实现一个简单的
capitalize
函数(将字符串首字母大写)。
步骤1:红
创建
stringUtils.test.js
,先写测试。
const { capitalize } = require('./stringUtils');
test('capitalizes the first letter of a string', () => {
expect(capitalize('hello')).toBe('Hello');
expect(capitalize('world')).toBe('World');
});
运行
npm test
,测试失败,因为
stringUtils.js
还不存在。这是预期的“红”。
步骤2:绿
创建
stringUtils.js
,用最简单的方式实现。
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
module.exports = { capitalize };
再次运行测试,变“绿”了。
步骤3:重构 审视我们的代码,目前很简单,可能不需要重构。但如果未来需求变更(比如要处理空字符串),我们可以在测试的保护下安全地修改。
TDD强迫你从使用者的角度思考接口,并且天然地保证了高测试覆盖率。对于逻辑清晰的工具函数或核心业务逻辑,强烈推荐尝试TDD。
5.3 组织测试代码的实用技巧
-
描述要清晰具体
:
test(‘works’)是糟糕的描述,test(‘returns null when input is empty string’)是好的描述。失败时一目了然。 - 一个测试,一个断言 :理想情况下,一个测试用例只验证一件事。这能让测试更清晰,也更容易定位问题。但这并非铁律,有时多个相关的断言放在一个测试里也是可以的,关键是逻辑要紧密相关。
-
使用
beforeEach和afterEach:如果多个测试需要相同的设置(如初始化一个对象、连接数据库)和清理工作,可以使用这些钩子函数,避免代码重复。
describe('database operations', () => {
let dbConnection;
beforeEach(() => {
// 在每个测试开始前,建立数据库连接
dbConnection = createConnection();
});
afterEach(() => {
// 在每个测试结束后,关闭连接
dbConnection.close();
});
test('query user by id', () => {
// 这里可以直接使用 dbConnection
const user = dbConnection.query('SELECT * FROM users WHERE id = 1');
expect(user.name).toBe('Alice');
});
test('insert a new user', () => {
// 另一个测试,同样有可用的 dbConnection
// ...
});
});
-
测试文件放在哪里?
两种主流方式:
-
与源码并列
:
src/math.js对应src/math.test.js。优点是导入路径短,结构清晰。 -
集中放在
__tests__目录 :如src/__tests__/math.test.js。优点是测试文件与源码分离,不会干扰项目结构。 根据团队习惯选择即可,Jest都支持。
-
与源码并列
:
6. 常见问题与排查技巧实录
在实际使用中,你肯定会遇到各种问题。这里记录了一些高频问题和我的解决思路。
6.1 “Cannot use import statement outside a module”
问题
:你在测试文件中使用了ES6的
import
语法,但Jest报错说不支持。
原因 :Node.js默认使用CommonJS模块系统。Jest运行在Node.js上,虽然它内部能处理ESM,但需要明确配置。
解决方案 :
-
确保
package.json中包含”type”: “module”。这告诉Node.js将.js文件视为ES模块。 -
如果项目是混合模块(既有ESM又有CommonJS),或者你不想设置
”type”: “module”,则需要通过Babel来转译。安装必要的包:npm install --save-dev babel-jest @babel/core @babel/preset-env -
创建
babel.config.js文件:module.exports = { presets: [['@babel/preset-env', {targets: {node: 'current'}}]], }; -
Jest会自动检测到Babel配置并使用它来转译代码,
import语法就可以正常工作了。
6.2 测试涉及DOM操作的前端代码报错
问题
:测试一个操作
document.getElementById
的函数时,报错
document is not defined
。
原因
:Jest默认的测试环境是Node.js,没有浏览器里的
document
和
window
对象。
解决方案 :
-
在
jest.config.js中设置testEnvironment: ‘jsdom’。jsdom是一个在Node.js中模拟浏览器DOM环境的库,Jest集成了它。 -
如果使用了像
@testing-library/jest-dom这样的库来扩展匹配器(如toBeInTheDocument),需要在jest.setup.js文件中引入:
并在// jest.setup.js import '@testing-library/jest-dom';jest.config.js的setupFilesAfterEnv中配置这个文件。
6.3 Mock不生效或行为不符合预期
问题
:明明用
jest.mock()
模拟了模块,但测试中调用的似乎还是原始模块。
原因与排查 :
-
作用域问题
:
jest.mock()调用会被提升到文件顶部执行。确保它在所有import语句之前(Jest会自动处理,但如果你在测试函数内部调用jest.mock是无效的)。 -
路径问题
:
jest.mock(‘./module’)中的路径必须是待测文件import或require该模块时使用的 完全相同 的路径。大小写和相对路径都要一致。 -
手动Mock与自动Mock
:
jest.mock(‘./module’)会使用Jest自动生成的模拟(所有函数都是返回undefined的Jest Mock函数)。如果你需要更复杂的模拟行为,可以在与模块同级的__mocks__目录下创建手动Mock文件。-
例如,要模拟
fs模块,创建__mocks__/fs.js。 -
然后在测试文件中写
jest.mock(‘fs’),Jest就会优先使用你手动创建的Mock。
-
例如,要模拟
6.4 异步测试超时或未等待完成
问题 :异步测试有时会误通过(没有等到Promise解决就结束),或者因超时而失败。
排查与解决 :
-
确保返回Promise
:如果你的测试不包含
async关键字,那么必须在expect语句前return那个Promise。// 正确 test(‘async test‘, () => { return fetchData().then(data => { expect(data).toBe(‘...‘); }); }); // 错误(可能误通过) test(‘async test‘, () => { fetchData().then(data => { expect(data).toBe(‘...‘); // 这个断言可能来不及执行 }); }); -
使用
async/await:这是最不容易出错的方式,清晰易懂。 -
调整超时时间
:默认超时是5秒。如果异步操作很慢,可以在测试用例或
describe块中单独设置:test(‘slow test‘, async () => { // ... 慢速操作 }, 10000); // 设置10秒超时
6.5 测试覆盖率报告解读
运行
npm test -- --coverage
或在配置中开启
collectCoverage
后,会生成覆盖率报告。
报告中主要看四个指标:
- Statements(语句覆盖率) :有多少比例的代码语句被执行了。
- Branches(分支覆盖率) :有多少比例的控制分支(如if/else)被执行了。 这个指标最重要 ,因为它能发现未测试的条件逻辑。
- Functions(函数覆盖率) :有多少比例的函数被调用了。
- Lines(行覆盖率) :有多少比例的代码行被执行了。
不要盲目追求100%的覆盖率,这通常不切实际且性价比低。应该 重点关注核心业务逻辑和复杂分支的覆盖 。覆盖率报告是一个发现测试盲点的好工具,而不是一个必须达成的KPI。
最后,记住测试的初衷是提升代码质量和开发效率,而不是增加负担。从简单的工具函数开始写起,逐渐培养“测试思维”,你会发现自己对代码的理解更深了,改起代码来也更有底气了。Jest就是这个过程中最得力的伙伴。

847

被折叠的 条评论
为什么被折叠?



