Skip to content

测试 ​

测试不是"写完代码后补的东西",是开发过程中的一部分。

1. 测试金字塔 ​

txt
        ╱╲
       ╱  ╲         E2E 测试(少量)
      ╱────╲        - 验证完整流程
     ╱      ╲       - 慢、脆弱
    ╱────────╲      集成测试(适量)
   ╱          ╲     - 验证组件协作
  ╱────────────╲    - 数据库、API
 ╱              ╲   单元测试(大量)
╱────────────────╲  - 验证行为或规则
                    - 快、稳定

2. 单元测试 ​

java
@Test
void shouldCalculateDiscount() {
    BigDecimal price = new BigDecimal("100");
    BigDecimal discount = OrderService.calculateDiscount(price, "VIP");
    assertThat(discount).isEqual(new BigDecimal("80"));
}

原则 ​

  • 验证一个明确的行为或业务规则,一个行为可以跨多个协作对象
  • 单元测试不依赖外部(数据库、网络)
  • 协作者行为需要隔离时才用 Mock,不默认 Mock 所有依赖
  • 命名清晰:should_预期行为_when_条件

涉及 SQL、事务、序列化、框架装配、外部协议的正确性时,应交给集成测试验证真实组件协作。

3. 集成测试 ​

集成测试验证组件协作,通常需要真实依赖(数据库、消息队列、API)。用容器化依赖(如 Testcontainers 启动真实 MySQL)减少关键依赖环境差异,测试应尽量对齐生产使用的服务版本和关键配置;涉及字符集、时区、事务隔离级别、数据库特定行为时,应显式验证相关配置与语义。

集成测试的落地代码(Testcontainers、@SpringBootTest)见 Spring 集成测试。

4. 测试覆盖率 ​

以下分档是经验参考,不是通用质量标准,不能据此判断核心逻辑是否已测试。

覆盖率经验参考建议
< 50%偏低可能存在测试缺口
50-70%一般覆盖常规路径,是否足够视风险而定
70-80%较好多数项目可参考的目标
> 80%较高核心业务建议达到

覆盖率衡量的是已执行的代码路径,不直接代表测试质量。行覆盖率不能说明条件分支是否充分验证,低覆盖率也不能单独证明核心逻辑缺少测试。

不要追求 100% 覆盖率:有些代码(getter/setter、配置类)不需要测试。

5. 测试最佳实践 ​

  1. 先写测试再写代码(TDD)或写完代码立即补测试
  2. 测试应该是确定性的:避免不可控的时间、随机数和外部状态
  3. 测试应该快速:单元测试尽量避免不必要的 I/O 和外部依赖,集成测试耗时应与验证范围匹配
  4. 测试应该独立:每个测试可以单独运行
  5. 测试失败时信息清晰:能看出哪里出了问题

Released under the MIT License.