来了解下单元测试吧。
单元测试是测试中的一个重要环节,它针对软件中的最小可测试单元进行验证,通常是指对代码中的单个函数、方法或模块进行测试。单元测试旨在确定特定部分代码的行为是否符合预期,通过针对单元代码的各种输入情况进行测试,来验证代码的正确性、稳定性和可靠性。
还会有一个概念叫集成测试,集成测试是将多个模块组合在一起,验证他们的相互协作是否正确。这种测试更关注于模块的接口及其交互。
那为什么要做单元测试?对于前端单元测试可以帮助开发者:
- 早期发现和修复问题,节省后续的修复成本。
- 改善代码质量,使其更加健壮和可靠。
- 为团队提供文档,帮助理解代码的预期行为。
在Node.js领域,有多个测试框架可供选择,以下是一些流行的选择:
- Mocha:一个功能丰富的测试框架,支持多种风格的测试(行为驱动、测试驱动等),强大的断言库。
- Jasmine:一个行为驱动的开发框架,简单易用,提供了丰富的断言和测试功能。
- Jest:由Facebook开发的测试框架,具备快速的测试运行和优雅的API,内置对ES6、异步测试的支持。有模拟函数、快照等特色功能。
- Chai:一个断言库,可以与Mocha等测试框架结合使用,支持多种断言风格。
- Vitest:Vitest 与 Jest 兼容,具有开箱即用的 ESM、Typescript 和 JSX 支持,并且由 esbuild 提供支持。它在测试过程中使用 Vite 开发服务器来转换你的文件,并监听我们的应用程序的相同配置(通过
vite.config.js
),从而消除了使用Jest等测试替代品所涉及的重复工作。
NodeJS 从 16 开始自带测试模块,包括了node:test和node:assert相对于比较主流的 jest
, mocha
等,好处是简单、轻量级,不需要安装额外的依赖,重要是速度很快!
接下来我们来看一下怎么使用这个模块进行单元测试。
参考资料:
- index.ts
typescript
/**
* @brief 根据输入数字返回字符串表示
* @param input 输入的数字
* @return 字符串结果:'Positive'(正数)、'Zero'(零)、'Error'(错误)
* @throws 当输入为负数时抛出 Error('Negative')
*/
export function testPrettier(input: number): string {
try {
if (input > 0) {
return 'Positive';
} else if (input < 0) {
throw new Error('Negative'); // 此行会爆出错误,中断程序执行
}
return 'Zero';
} catch (err) {
console.error(err);
return 'Error';
}
}
console.log("=============start===============");
const message: string = 'Hello, World!';
console.log(message);
console.log(testPrettier(5));
console.log(testPrettier(0));
console.log(testPrettier(-5));
console.log("=============end===============");
- 测试文件
ts
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { testPrettier } from '../src/index.ts';
describe('Test: base test', () => {
it('测试正整数输入 (5)', () => {
console.log('STEP: 验证输入5时返回"Positive"');
assert.deepStrictEqual(
testPrettier(5),
'Positive'
);
});
it('测试零输入 (0)', () => {
console.log('STEP: 验证输入0时返回"Zero"');
assert.deepStrictEqual(testPrettier(0), 'Zero');
});
it('测试负整数输入 (-5)', () => {
console.log('STEP: 验证输入-5时返回"Error"');
assert.deepStrictEqual(testPrettier(-5), 'Error');
});
});
assert.deepStrictEqual函数原型:
typescript
assert.deepStrictEqual(actual, expected[, message])
该函数接受上述和以下描述的以下参数:
- **actual: **此参数保存需要评估的实际值。它是任何类型。
- **expected: **此参数保存与实际值匹配的期望值。它是任何类型。
- **message: **此参数保存字符串或错误类型的错误消息。它是一个可选参数。
**返回值:**此函数返回对象类型的断言错误。
我们要使用node:test,还需要安装依赖:
shell
npm i -D @types/node
由于我们的测试文件是ts,ts文件还需要编译,我们这里可以安装tsx工具,直接运行ts文件:
shell
npm i -D tsx
json
"scripts": {
"test": "tsx test/index.test.ts",
//......
},
然后我们就可以运行测试了。
shell
D:\sumu_blog\ts-demo [master ↑2 +1 ~3 -0 !]> npm run test
> ts-demo@1.0.0 test
> tsx test/index.test.ts
=============start===============
Hello, World!
Positive
Zero
Error: Negative
at testPrettier (D:\sumu_blog\ts-demo\src\index.ts:22:13)
at <anonymous> (D:\sumu_blog\ts-demo\src\index.ts:36:13)
at Object.<anonymous> (D:\sumu_blog\ts-demo\src\index.ts:37:46)
at Module._compile (node:internal/modules/cjs/loader:1730:14)
at Object.transformer (D:\sumu_blog\ts-demo\node_modules\tsx\dist\register-D46fvsV_.cjs:3:1104)
at Module.load (node:internal/modules/cjs/loader:1465:32)
at Function._load (node:internal/modules/cjs/loader:1282:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
at Module.require (node:internal/modules/cjs/loader:1487:12)
Error
=============end===============
STEP: 验证输入5时返回"Positive"
STEP: 验证输入0时返回"Zero"
STEP: 验证输入-5时返回"Error"
Error: Negative
at testPrettier (D:\sumu_blog\ts-demo\src\index.ts:22:13)
at TestContext.<anonymous> (D:\sumu_blog\ts-demo\test\index.test.ts:21:28)
at Test.runInAsyncScope (node:async_hooks:214:14)
at Test.run (node:internal/test_runner/test:1047:25)
at Suite.processPendingSubtests (node:internal/test_runner/test:744:18)
at Test.postRun (node:internal/test_runner/test:1173:19)
at Test.run (node:internal/test_runner/test:1101:12)
at async Suite.processPendingSubtests (node:internal/test_runner/test:744:7)
▶ Test: base test
✔ 测试正整数输入 (5) (1.096ms)
✔ 测试零输入 (0) (0.3967ms)
✔ 测试负整数输入 (-5) (0.774ms)
✔ Test: base test (3.331ms)
ℹ tests 3
ℹ suites 1
ℹ pass 3
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 9.4593
Error: Negative这部分就是因为调用了testPrettier(-5),这个时候函数抛出了异常,然后被捕获,通过console.error(err);打印出来的。
Vitest(发音为 "veetest") 是由 Vite 驱动的下一代测试框架。详细的介绍直接看文档吧:为什么是 Vitest | 指南 | Vitest,它有什么特点?还是看文档吧,文档写的还是很详细的:主要功能 | 指南 | Vitest
shell
npm install -D vitest