刚学TDD那会儿,我也以为“先写测试再写代码”是银弹——结果在做一个临时改版的后台管理页时硬套TDD,光写测试就卡了两天,最后删掉所有测试用例,直接开干。后来才明白:TDD不是万能膏药,它特别挑项目。
逻辑清晰、边界明确的模块最吃香
比如你正在写一个金额计算服务:输入订单总价、优惠券、满减规则,输出最终应付金额。这类业务规则稳定、输入输出可穷举,TDD就能大显身手。写个测试:
test("满300减50,优惠券10元,应付240元", () => {
const result = calculate({ total: 300, coupon: 10, discountRule: "300-50" });
expect(result).toBe(240);
});边写边跑,逻辑一歪马上报警,比靠人眼盯日志快多了。需要长期维护、多人协作的老系统
团队接手一个运行五年的电商结算模块,文档缺失、注释过期、改一行怕崩一片。这时候补全TDD不是负担,是救命绳。新加一个“积分抵扣”功能前,先补上核心路径的测试用例,哪怕只有3个关键case,后续每次重构都有底气——只要测试绿,心里就踏实。
算法类、工具库、SDK 这类“被别人调用”的代码
你封装一个日期格式化工具函数,暴露给前端多个项目使用。用户不管你怎么实现,只认输入输出是否符合约定。TDD天然逼你定义清楚接口契约:
formatDate(new Date("2023-08-15"), "YYYY-MM-DD") // → "2023-08-15"
formatDate(new Date("2023-08-15"), "MM/DD/YYYY") // → "08/15/2023"测得越细,别人用得越放心,提issue的都少了。但这些项目真不适合硬上TDD
原型验证阶段(比如老板说“三天做个Demo看看效果”),写测试的时间成本远超价值;UI频繁变动的页面(今天按钮在左,明天挪到右),测试用例跟着天天改,纯属自我消耗;还有那种重度依赖外部API、网络状态、第三方登录的模块——光Mock就折腾半天,不如先跑通流程再补测。
TDD不是考试打分,是帮你把代码写得更稳、改得更敢的一种节奏。选对项目,它就是顺手的螺丝刀;硬塞进不合适的地方,反倒拧花螺纹。