一、什么是 TDD

TDD (Test‑Driven Development,测试驱动开发) 核心思想:先写测试,再写业务代码,让测试来驱动功能实现,和传统思路反过来。

传统开发:写业务代码 → 写完再写测试 TDD 开发:先写测试用例 (现在一定会报错) → 写最少代码让测试通过 → 重构优化

二、TDD 开发三步法

  1. 红 (Red):编写一个失败的单元测试。此时功能代码还不存在 / 不完善,运行测试直接报错。
  2. 绿 (Green):编写最少、最简单的业务代码,让这条测试刚好通过,不追求优雅。
  3. 重构 (Refactor):优化代码结构、消除重复,保证所有测试依然全部通过

循环往复,每一个小功能都走一遍红‑绿‑重构。

TDD 不是为了多写测试;是用测试来定义需求

三、TDD 优点 & 缺点

优点

  1. 代码天然可测试,高内聚低耦合
  2. 需求通过测试用例显性表达,减少理解偏差
  3. 修改、重构时快速回归,防止改坏原有功能
  4. 自动形成一套完整单元测试集
  5. 逼你从小粒度、简单功能开始实现

缺点

  1. 前期速度慢,要花时间设计测试
  2. 不适合超复杂算法、需求极不稳定频繁大改场景
  3. 需要开发者熟练单元测试框架
  4. 只能保证 “代码满足测试用例”,不能保证覆盖全部业务场景

四、Demo:金额折扣工具

需求:

  • 原价大于等于 100,打 9 折
  • 原价小于 100,不打折

TDD 流程演示

1.Red:先写测试

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class DiscountUtilTest {

    //测试满100打9折
    @Test
    void calcDiscount_priceOver100(){
        DiscountUtil util = new DiscountUtil();
        double pay = util.calc(200);
        assertEquals(180,pay,0.001);
    }

    //小于100不打折
    @Test
    void calcDiscount_priceLess100(){
        DiscountUtil util = new DiscountUtil();
        double pay = util.calc(50);
        assertEquals(50,pay,0.001);
    }
}

🔴报错,DiscountUtil 不存在

2.Green 最简实现先过第一个测试

public class DiscountUtil {
    public double calc(double price) {
        return 180;
    }
}

第一条测试过,第二条失败,继续完善

3.完善代码,全部用例通过

public class DiscountUtil {
    public double calc(double price) {
        if(price >=100){
            return price * 0.9;
        }
        return price;
    }
}

✅全部测试通过,再做重构,比如抽常量折扣率

public class DiscountUtil {
    private static final double DISCOUNT_RATE = 0.9;
    public double calc(double price) {
        if(price >=100){
            return price * DISCOUNT_RATE;
        }
        return price;
    }
}

五、TDD 和普通单元测试区别

TDD开发后补单元测试
顺序测试先行业务代码先行
作用驱动设计、定义需求、反馈验证已完成代码正确性
时机写功能前写完功能以后
设计影响倒逼接口设计简单易测很难改变已经写好的糟糕设计
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐