← 返回博客

测试策略实战:从单元测试到集成测试的工程方法

测试不是"测了就比不测好",而是"测什么、怎么测、测多少"的问题。本文从测试金字塔出发,讨论单元测试、集成测试、端到端测试的职责边界和覆盖率策略,以及如何让测试成为开发流程的一部分而不是负担——适合正在搭建或优化测试体系的团队。

先说结论:测试的关键不是”测了”,而是”测对了”

很多团队把测试当成”上线前的安全检查”,为了赶进度压缩测试时间,或者为了指标盲目追求覆盖率。这两种做法都偏离了测试的本质——测试是开发流程的一部分,不是门禁。

本文从测试金字塔出发,讨论每种测试的职责边界和落地方法。


1. 测试金字塔

       /\
      /  \         E2E 测试(少而精)
     /    \
    /------\
   / 集成测试 \     (关键路径覆盖)
  /------------\
 /  单元测试    \   (多而快,覆盖核心逻辑)
/----------------\

各层职责

层级速度数量职责
单元测试毫秒级验证单个函数/类的行为
集成测试秒级验证模块间交互
E2E 测试分钟级验证关键用户流程

2. 单元测试

2.1 测什么

  • 业务逻辑(计算、校验、转换)
  • 边界条件(空值、越界、异常输入)
  • 错误处理(函数在异常情况下是否返回正确的错误)

2.2 不测什么

  • 框架行为(Express 的路由、React 的渲染——框架自己已经测过了)
  • 数据库查询(那是集成测试的事)
  • 第三方 API 调用(Mock 掉,只验证调用参数和返回值处理)

2.3 示例

// 待测函数
function calculateDiscount(amount: number, level: 'bronze' | 'silver' | 'gold'): number {
  const rates = { bronze: 0, silver: 0.1, gold: 0.2 };
  return amount * (1 - rates[level]);
}

// 测试
describe('calculateDiscount', () => {
  it('returns full amount for bronze', () => {
    expect(calculateDiscount(100, 'bronze')).toBe(100);
  });
  it('applies 10% discount for silver', () => {
    expect(calculateDiscount(100, 'silver')).toBe(90);
  });
  it('applies 20% discount for gold', () => {
    expect(calculateDiscount(100, 'gold')).toBe(80);
  });
  it('handles zero amount', () => {
    expect(calculateDiscount(0, 'gold')).toBe(0);
  });
});

3. 集成测试

3.1 测什么

  • API 接口的请求和响应
  • 数据库读写操作
  • 服务之间的消息传递

3.2 配置

// 使用测试数据库
beforeAll(async () => {
  await db.migrate.latest();
  await db.seed.run();
});

afterAll(async () => {
  await db.destroy();
});

describe('POST /users', () => {
  it('creates a new user', async () => {
    const res = await request(app)
      .post('/users')
      .send({ name: 'test', email: 'test@test.com' });
    expect(res.status).toBe(201);
    expect(res.body.name).toBe('test');
  });
});

4. 端到端测试

4.1 测什么

  • 关键用户流程(注册、登录、下单)
  • 跨系统的交互(前端 → API → 数据库 → 第三方服务)

4.2 原则

  • 只测关键路径,不测所有路径
  • 用 Cypress 或 Playwright
  • 在 CI 中每天跑一次,或者在合并到主干前跑

5. 测试策略总结

测试类型覆盖目标运行频率允许失败?
单元测试核心逻辑 80%+每次提交不允许
集成测试关键 API 路径每天不允许
E2E 测试关键用户流程合并前可以(需人工确认)

测试策略的成熟度不看”有多少测试”,而看”测试在多大程度上融入了开发流程”。 最好的状态是:写测试和写代码一样自然,不写测试反而觉得不习惯。

需要测试体系建设或技术咨询?联系我们,说清你的项目规模与技术栈,24 小时内回可行性。

相关阅读

常见问题

测试应该覆盖多少代码?

不要追求 100% 代码覆盖率。核心逻辑(业务规则、数据处理、API 接口)应该覆盖 80% 以上,UI 层和胶水代码覆盖 50% 就够了。重点不是覆盖率数字,而是"关键路径有没有测试"。一个只有 60% 覆盖率但核心逻辑全测了的项目,比一个 90% 覆盖率但核心逻辑没测的项目好得多。

单元测试和集成测试的分界线在哪?

单元测试不依赖外部系统(数据库、API、文件系统),所有外部依赖都 Mock 掉。集成测试验证模块之间的交互是否正常,依赖真实的外部系统(测试数据库、测试 API)。分界线:如果你的测试需要启动数据库,那就是集成测试,不是单元测试。

测试太慢怎么办?

分层运行:单元测试每次提交都跑(几秒到几十秒),集成测试每天跑一次(几分钟),端到端测试在合并到主干前跑(十几分钟)。慢的测试不是不写,而是不阻塞开发流程。

TDD(测试驱动开发)真的有用吗?

有用,但需要练习。TDD 的核心价值不是"先写测试再写代码",而是"写代码之前先想清楚预期行为"。如果你刚开始尝试 TDD,建议从 bug 修复开始——先写一个重现 bug 的测试,再修复代码,测试通过。这样既有成就感,又能确保 bug 不会再回来。

本文来自 AI Enable Harness 一线交付实践。需要同类系统或优化服务?

📡 本文同步发布平台: CSDN 知乎

订阅博客更新

新文章发布后第一时间邮件通知。不定期发送,不推销。

订阅 →