# 测试文档 ## 测试框架 本项目使用 **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)