T

tdd

测试驱动开发。当用户希望以测试优先的方式构建功能或修复错误、提到“红-绿-重构”,或希望编写集成测试时使用。

TDD 测试驱动开发技能 - 用红绿循环写出值得保留的测试

技能概述

TDD 技能让 AI 助手按 red → green 的红绿循环带你做测试驱动开发:先写一个失败的测试,再写刚好让它通过的最少代码,并且测试只写在事先和你约定好的接缝上。

适用场景

  1. 开发新功能,想先写测试再写实现:当你希望以测试驱动的方式构建一个功能,而不是写完代码再回头补测试时,这个技能会一个接缝、一个测试、一段最小实现地往下走。

  2. 修 bug 时先写一个复现测试:用一条能稳定复现缺陷的测试把问题钉住,再改代码让它变绿,避免「改好了但不知道有没有改坏别的地方」。

  3. 需要集成测试,而不只是单元测试:技能本身覆盖集成测试的写法,测试放在公共接口这一层,验证的是真实行为而不是内部结构。

核心功能

  1. 红绿循环执行:严格先红后绿——先写失败测试,再写只够通过它的代码。不会提前实现未来的测试,也不会顺手加投机性的功能,每次循环只推进一个垂直切片(tracer bullet),根据上一轮学到的东西决定下一步。

  2. 接缝(seam)约定:写任何测试之前,先列出准备测试的接缝并和你确认。接缝指的是你观察行为的那个公共边界,测试只住在接缝上,绝不伸进内部。因为不可能什么都测,事先约定接缝能让测试精力落在关键路径和复杂逻辑上,而不是每个边缘情况。如果你的接口形状本身还在犹豫(模块该多深、接缝该放哪、接口该暴露什么),技能会引导你参考 codebase-design 的相关词汇来对齐。

  3. 反模式把关:技能明确列出三类要避开的测试反模式并主动规避——

    • 实现耦合:mock 内部协作者、测试私有方法、或者绕开接口去查数据库这类「侧信道」验证。特征是重构之后行为没变,测试却挂了。
    • 同义反复:断言用和代码一样的方式重算期望值(比如 expect(add(a, b)).toBe(a + b),或者手搓一个和实现同思路的快照),这种测试靠构造通过,永远不会和代码产生分歧。期望值必须来自独立的事实来源:已知正确的字面量、手算的例子、或者规格说明。
    • 水平切片:先一口气写完所有测试再写实现。批量测试验证的是「想象中」的行为,测的是形状而不是用户可感知的行为,而且还没理解实现就把测试结构定死了。

常见问题

TDD 一定要先写测试吗?写完代码再补测试算不算?

不算。这个技能的核心规则就是 red before green:失败的测试必须先出现,然后才写刚好够通过它的代码。补测试是在已经知道答案之后写的,很难验证测试本身是否真的能失败。

循环里也不允许一次把所有测试写完——那是「水平切片」的反模式,验证的是想象出来的行为,还提前把测试结构定死了。技能走的是垂直切片:一个接缝 → 一个测试 → 一段最小实现,每个测试都像一发曳光弹,根据上一轮学到的东西决定下一步。重构同样不属于这个循环,它归评审阶段(对应 code-review 技能)管。

什么是测试接缝(seam)?为什么写之前要先约定?

接缝就是你要测试的那个公共边界——在接口这一层观察行为,而不用伸手进去看内部。技能要求只在事先约定好的接缝上写测试,未经确认的接缝不写。原因是测试资源有限,事先对齐接缝才能把力气花在关键路径和复杂逻辑上,而不是铺满每一个边缘情况。

如果你的接口形状本身还没定(模块该多深、接缝该放哪、接口该暴露什么),技能会引导你参考 codebase-design 的模块、接口、深度、适配器等词汇来对齐。

为什么我的测试一重构就挂?

大概率是实现耦合。测试如果 mock 了内部协作者、直接测私有方法,或者绕过接口用侧信道(比如直接查数据库)验证,那它测的就不是行为而是结构。结构一变,行为没变,测试照样红。判断标准很简单:重构之后行为没变,测试却失败了,就说明这个测试写错了层。