Files
qiming/qiming-file-server/tests

测试文档

测试框架

本项目使用 Jest 作为测试框架,配合 Supertest 进行 API 集成测试。

测试目录结构

tests/
├── setup.js                    # 测试环境配置
├── unit/                       # 单元测试
│   ├── errorHandler.test.js
│   ├── restartJudgeUtils.test.js
│   └── dependencyManager.test.js
└── integration/                # 集成测试(待添加)
    └── api.test.js

运行测试

运行所有测试

npm test

运行测试并监听文件变化

npm run test:watch

只运行单元测试

npm run test:unit

只运行集成测试

npm run test:integration

查看测试覆盖率

测试覆盖率报告会自动生成在 coverage/ 目录下。

# 运行测试后查看覆盖率
npm test

# 在浏览器中查看详细报告
open coverage/lcov-report/index.html

测试覆盖率目标

当前设置的覆盖率阈值:

  • 分支覆盖率: 50%
  • 函数覆盖率: 50%
  • 行覆盖率: 50%
  • 语句覆盖率: 50%

编写测试

单元测试示例

// 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("错误信息");
  });
});

集成测试示例

// 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 中提供了全局测试工具:

// 生成测试用的 projectId
const projectId = global.testUtils.generateProjectId();

// 生成测试用的版本号
const version = global.testUtils.generateVersion();

// 等待函数
await global.testUtils.sleep(1000); // 等待1秒

测试最佳实践

1. 测试命名

  • 使用清晰的描述性名称
  • 使用 describe 分组相关测试
  • 使用 testit 描述单个测试用例

2. 测试隔离

  • 每个测试应该独立运行
  • 使用 beforeEachafterEach 清理状态
  • 避免测试之间的依赖关系

3. 测试覆盖

  • 测试正常情况
  • 测试边界条件
  • 测试错误情况
  • 测试异常输入

4. Mock 和 Stub

// Mock 外部依赖
jest.mock("../../src/utils/externalService");

// Mock 函数
const mockFn = jest.fn().mockReturnValue("mocked value");

// 验证调用
expect(mockFn).toHaveBeenCalledWith("expected argument");
expect(mockFn).toHaveBeenCalledTimes(1);

5. 异步测试

// 使用 async/await
test("异步操作", async () => {
  const result = await asyncFunction();
  expect(result).toBe("expected");
});

// 使用 Promise
test("Promise 操作", () => {
  return promiseFunction().then((result) => {
    expect(result).toBe("expected");
  });
});

常用断言

// 相等性
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. 运行单个测试文件

npm test -- tests/unit/errorHandler.test.js

2. 运行匹配的测试

npm test -- --testNamePattern="应该正确创建"

3. 使用 Node 调试器

node --inspect-brk node_modules/.bin/jest --runInBand

持续集成

测试应该在每次提交前运行:

# 提交前运行测试
npm test

# 如果测试通过,再提交代码
git add .
git commit -m "feat: 添加新功能"

测试环境配置

测试环境使用独立的配置:

  • 端口: 10003
  • 日志: 禁用控制台输出
  • 超时: 10 秒

这些配置在 tests/setup.js 中设置。

注意事项

  1. 不要提交失败的测试 - 确保所有测试通过后再提交
  2. 保持测试快速 - 单元测试应该在毫秒级完成
  3. 定期更新测试 - 代码变更时同步更新测试
  4. 编写有意义的测试 - 测试应该验证真实的业务逻辑
  5. 避免测试实现细节 - 测试行为,而非实现

贡献测试

欢迎为项目添加更多测试!优先添加:

  1. 核心业务逻辑的单元测试
  2. API 端点的集成测试
  3. 边界条件和错误处理测试
  4. 工具函数的测试

相关资源