测试驱动开发 / Test-Driven Development
模型已经理解测试驱动开发。本技能只约束容易失真的部分:测试真实行为,确认失败原因,并避免为了流程制造低价值用例。
先决定证据寿命
每次改动都要有与风险匹配的验证证据,但不等于每次都新增永久测试。优先复用现有保护网;只有稳定契约、真实回归风险、可靠自动化接缝同时存在,且预期长期收益高于测试与夹具的维护成本时,才新增永久自动化测试。上游技能需要补足保护证据时,是否新增永久测试统一按本节判断;缺陷复现、当前验证和永久回归保护的用途与寿命不同,不能互相冒充。
可逆、低影响的改动不新增复刻实现的测试。选择测试验证时,用例必须有实际意义且确有必要;不制造实现细节断言、浅层用例或脆弱文本快照。不满足永久测试门槛时,选择可复核的当前证据,例如现有测试、类型或 Schema 检查、Lint、构建或定向命令、人工或视觉检查、日志与监控,并记录证据局限。
开始前
- 读取验收标准或
validation-contract.md;每条验收断言定义要证明的行为,不等于单个验证用例。先按“验证方式”选择证据类型,再按风险展开为一个或多个必要用例;测试类断言可以对应多个测试用例。缺陷修复以问题事实和复现路径为准。 - 从仓库根检查
docs/rules/test/。仓库根用git rev-parse --show-toplevel确认;从每个受影响文件或目录向仓库根查找更近的docs/rules/test/,两层都读取,目标路径更近的子包级规则优先;非 git 仓库回退到当前目录作为根,仍按受影响路径查找。 - 扫描相邻测试,沿用现有测试框架、命名和夹具。
最小循环
决定新增永久自动化测试后:
- 选择接缝:从公共接口或可观察副作用验证行为,选择能捕捉目标风险的最低有效层级。
- 建立证据:新行为或缺陷修复先写当前切片的最小测试并运行,确认它因目标行为缺失而失败,而不是因语法、导入或夹具错误失败。
- 最小实现:只写足以让当前测试通过的实现,不提前满足想象中的后续用例。
- 纵向推进:默认按小行为切片完成验证再推进;同一契约自然适合参数化用例时,可以一起定义并运行,不为顺序拆散简洁用例,也不先铺大量未经验证的测试。
- 回归验证:运行与本次行为变化及回归风险相关的测试。
重构不必制造失败测试:先确认目标行为已有保护;保护缺失且满足上述条件时补特征测试,然后在持续通过的状态下改结构。没有有效自动化接缝时,记录原因并使用最接近真实行为的可执行验证。
运行与改动匹配的验证并完成项目必需检查;通过后继续推进交付,停止扩大或重复验证。只有新变化、新失败或尚未解决的具体疑点才追加检查;哪些证据失效就补哪些,不因归档或无关文字修改重跑全套。交付证据按 ../spec-design/references/validation-results-template.md 记录,开发试跑不逐次入档;最终完成判断遵循工作流规则。
测试取舍
- 测试行为,不测试私有方法、内部调用顺序或实现结构。
- 优先使用真实实现或内存替身;只在网络、数据库、时钟、文件系统等系统边界模拟。
- 用验收标准、已知风险和缺陷事实选择用例,不按通用场景清单机械穷举。
- 测试是维护资产,不以用例数量、断言数量或覆盖率增长本身为目标。
- 不为说明文字、提示词措辞或日志文案写精确匹配测试;只有文本属于机器协议、稳定文件格式或用户可见契约时才断言。
- 不因实现早于验证出现就删除可用代码;先判断证据寿命,需要永久保护时补上能证明行为的测试,否则保留与风险匹配的当前证据。