编写测试
Node.js 有几个常用测试框架,包括 Jest
、Mocha
、Jasmine
等。
此项目使用 Jest,因为它是一个简单易用,使人心情愉悦的 JavaScript 测试框架。
describe
用于在逻辑结构中将相关测试用例组合在一起。
describe(name: string, fn: () => void): void;
beforeAll
、beforeEach
、afterAll
和 afterEach
函数允许在测试套件或单个测试用例之前或之后准备或清理资源。
这对于执行诸如初始化变量、创建临时文件或清理资源等操作非常有用。
expect(...).toEqual(...)
是一个断言语句,用于断言一个值或对象是否等于预期值。
expect(received).toEqual(expected);
安装 jest
及其 TypeScript 支持(如果尚未安装):
npm install --save-dev jest ts-jest @types/jest
更新 package.json 以使用 jest
作为自定义测试脚本,并添加 jest
配置部分:
"scripts": {
"test": "npx jest",
...
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
}
}
test/grep.test.ts:
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { promisify } from 'util';
import { grep, grepRecursive, grepCount, MatchResult } from '../lib/grep';
const mkdtemp = promisify(fs.mkdtemp);
const writeFile = promisify(fs.writeFile);
let tmpDir: string;
beforeAll(async () => {
// 在所有测试之前准备资源
tmpDir = await mkdtemp(path.join(os.tmpdir(), 'grep-test-'));
});
afterAll(() => {
// 在所有测试之后清理资源
// 例如,可以删除临时目录
fs.rmSync(tmpDir, { recursive: true });
});
beforeEach(() => {
// 在每个测试之前准备资源
});
afterEach(() => {
// 在每个测试之后清理资源
});
describe('grep', () => {
it('should match lines in a file', async () => {
const filePath = path.join(tmpDir, 'single-file.txt');
await writeFile(filePath, 'This is an example line\nThis line should not match');
const pattern = 'example';
const options = { ignoreCase: false, invertMatch: false };
const result = await grep(pattern, filePath, options);
expect(result[filePath]).toEqual([[1, 'This is an example line']]);
});
it('should handle invertMatch correctly', async () => {
const filePath = path.join(tmpDir, 'single-file.txt');
await writeFile(filePath, 'This is an example line\nThis line should not match');
const pattern = 'example';
const options = { ignoreCase: false, invertMatch: true };
const result = await grep(pattern, filePath, options);
expect(result[filePath]).toEqual([[2, 'This line should not match']]);
});
});
describe('grepRecursive', () => {
it('should match lines in files recursively', async () => {
const dirPath = path.join(tmpDir, 'nested-directory');
const filePath1 = path.join(dirPath, 'file1.txt');
const filePath2 = path.join(dirPath, 'subdir', 'file2.txt');
await fs.promises.mkdir(path.join(dirPath, 'subdir'), { recursive: true });
await writeFile(filePath1, 'This is an example line');
await writeFile(filePath2, 'Another example line');
const pattern = 'example';
const options = { ignoreCase: false, invertMatch: false };
const result = await grepRecursive(pattern, dirPath, options);
expect(result).toEqual({
[filePath1]: [[1, 'This is an example line']],
[filePath2]: [[1, 'Another example line']],
});
});
it('should handle invertMatch correctly in recursive search', async () => {
const dirPath = path.join(tmpDir, 'nested-directory');
const filePath1 = path.join(dirPath, 'file1.txt');
const filePath2 = path.join(dirPath, 'subdir', 'file2.txt');
await fs.promises.mkdir(path.join(dirPath, 'subdir'), { recursive: true });
await writeFile(filePath1, 'This is an example line');
await writeFile(filePath2, 'This line should not match');
const pattern = 'example';
const options = { ignoreCase: false, invertMatch: true };
const result = await grepRecursive(pattern, dirPath, options);
expect(result).toEqual({
[filePath1]: [],
[filePath2]: [[1, 'This line should not match']],
});
});
});
describe('grepCount', () => {
it('should count the total number of matches in the result', () => {
const result: MatchResult = {
'file1.txt': [[1, 'Match line 1'], [3, 'Match line 3']],
'file2.txt': [[2, 'Match line 2']],
};
const count = grepCount(result);
expect(count).toBe(3);
});
});
运行测试:
npx jest
# 或
npm test
应该会得到如下的测试结果:
> lr_grepjs@1.0.0 test
> npx jest
PASS test/grep.test.ts
grep
✓ should match lines in a file (10 ms)
✓ should handle invertMatch correctly (1 ms)
grepRecursive
✓ should match lines in files recursively (3 ms)
✓ should handle invertMatch correctly in recursive search (3 ms)
grepCount
✓ should count the total number of matches in the result (1 ms)
Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 1.63 s, estimated 2 s
Ran all test suites.
如果有错误,将获得类似下面的断言错误消息:
> npx jest
FAIL test/grep.test.ts
grep
✕ should match lines in a file (10 ms)
✓ should handle invertMatch correctly (1 ms)
grepRecursive
✓ should match lines in files recursively (2 ms)
✓ should handle invertMatch correctly in recursive search (2 ms)
grepCount
✓ should count the total number of matches in the result (1 ms)
● grep › should match lines in a file
expect(received).toEqual(expected) // deep equality
- Expected - 1
+ Received + 1
Array [
Array [
1,
- "This is an example line2",
+ "This is an example line",
],
]
40 | const result = await grep(pattern, filePath, options);
41 |
> 42 | expect(result[filePath]).toEqual([[1, 'This is an example line2']]);
| ^
43 | });
44 |
45 | it('should handle invertMatch correctly', async () => {
at Object.<anonymous> (test/grep.test.ts:42:30)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 4 passed, 5 total
Snapshots: 0 total
Time: 1.601 s, estimated 2 s
Ran all test suites.
然后,你可以根据此错误消息修复你的代码。