Files
qiming/qiming-file-server/tests/README.md

276 lines
5.5 KiB
Markdown

# 测试文档
## 测试框架
本项目使用 **Jest** 作为测试框架,配合 **Supertest** 进行 API 集成测试。
## 测试目录结构
```
tests/
├── setup.js # 测试环境配置
├── unit/ # 单元测试
│ ├── errorHandler.test.js
│ ├── restartJudgeUtils.test.js
│ └── dependencyManager.test.js
└── integration/ # 集成测试(待添加)
└── api.test.js
```
## 运行测试
### 运行所有测试
```bash
npm test
```
### 运行测试并监听文件变化
```bash
npm run test:watch
```
### 只运行单元测试
```bash
npm run test:unit
```
### 只运行集成测试
```bash
npm run test:integration
```
### 查看测试覆盖率
测试覆盖率报告会自动生成在 `coverage/` 目录下。
```bash
# 运行测试后查看覆盖率
npm test
# 在浏览器中查看详细报告
open coverage/lcov-report/index.html
```
## 测试覆盖率目标
当前设置的覆盖率阈值:
- **分支覆盖率**: 50%
- **函数覆盖率**: 50%
- **行覆盖率**: 50%
- **语句覆盖率**: 50%
## 编写测试
### 单元测试示例
```javascript
// tests/unit/myModule.test.js
const { myFunction } = require("../../src/utils/myModule");
describe("我的模块测试", () => {
test("应该返回正确的结果", () => {
const result = myFunction("input");
expect(result).toBe("expected output");
});
test("应该处理错误情况", () => {
expect(() => {
myFunction(null);
}).toThrow("错误信息");
});
});
```
### 集成测试示例
```javascript
// tests/integration/api.test.js
const request = require("supertest");
const app = require("../../src/server");
describe("API 集成测试", () => {
test("GET /api/build/list-dev 应该返回进程列表", async () => {
const response = await request(app).get("/api/build/list-dev").expect(200);
expect(response.body.success).toBe(true);
expect(Array.isArray(response.body.list)).toBe(true);
});
});
```
## 测试工具函数
`tests/setup.js` 中提供了全局测试工具:
```javascript
// 生成测试用的 projectId
const projectId = global.testUtils.generateProjectId();
// 生成测试用的版本号
const version = global.testUtils.generateVersion();
// 等待函数
await global.testUtils.sleep(1000); // 等待1秒
```
## 测试最佳实践
### 1. 测试命名
- 使用清晰的描述性名称
- 使用 `describe` 分组相关测试
- 使用 `test``it` 描述单个测试用例
### 2. 测试隔离
- 每个测试应该独立运行
- 使用 `beforeEach``afterEach` 清理状态
- 避免测试之间的依赖关系
### 3. 测试覆盖
- 测试正常情况
- 测试边界条件
- 测试错误情况
- 测试异常输入
### 4. Mock 和 Stub
```javascript
// Mock 外部依赖
jest.mock("../../src/utils/externalService");
// Mock 函数
const mockFn = jest.fn().mockReturnValue("mocked value");
// 验证调用
expect(mockFn).toHaveBeenCalledWith("expected argument");
expect(mockFn).toHaveBeenCalledTimes(1);
```
### 5. 异步测试
```javascript
// 使用 async/await
test("异步操作", async () => {
const result = await asyncFunction();
expect(result).toBe("expected");
});
// 使用 Promise
test("Promise 操作", () => {
return promiseFunction().then((result) => {
expect(result).toBe("expected");
});
});
```
## 常用断言
```javascript
// 相等性
expect(value).toBe(expected); // ===
expect(value).toEqual(expected); // 深度相等
// 真值
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();
// 数字
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// 字符串
expect(string).toMatch(/pattern/);
expect(string).toContain("substring");
// 数组
expect(array).toContain(item);
expect(array).toHaveLength(3);
// 对象
expect(object).toHaveProperty("key");
expect(object).toHaveProperty("key", "value");
// 异常
expect(() => {
throw new Error("error");
}).toThrow("error");
```
## 调试测试
### 1. 运行单个测试文件
```bash
npm test -- tests/unit/errorHandler.test.js
```
### 2. 运行匹配的测试
```bash
npm test -- --testNamePattern="应该正确创建"
```
### 3. 使用 Node 调试器
```bash
node --inspect-brk node_modules/.bin/jest --runInBand
```
## 持续集成
测试应该在每次提交前运行:
```bash
# 提交前运行测试
npm test
# 如果测试通过,再提交代码
git add .
git commit -m "feat: 添加新功能"
```
## 测试环境配置
测试环境使用独立的配置:
- 端口: 10003
- 日志: 禁用控制台输出
- 超时: 10 秒
这些配置在 `tests/setup.js` 中设置。
## 注意事项
1. **不要提交失败的测试** - 确保所有测试通过后再提交
2. **保持测试快速** - 单元测试应该在毫秒级完成
3. **定期更新测试** - 代码变更时同步更新测试
4. **编写有意义的测试** - 测试应该验证真实的业务逻辑
5. **避免测试实现细节** - 测试行为,而非实现
## 贡献测试
欢迎为项目添加更多测试!优先添加:
1. 核心业务逻辑的单元测试
2. API 端点的集成测试
3. 边界条件和错误处理测试
4. 工具函数的测试
## 相关资源
- [Jest 文档](https://jestjs.io/docs/getting-started)
- [Supertest 文档](https://github.com/visionmedia/supertest)
- [测试最佳实践](https://github.com/goldbergyoni/javascript-testing-best-practices)