# Tdd

> 测试驱动开发(Test-Driven Development)。当用户希望以测试优先的方式构建功能或修复 bug、提到 "red-green-refactor"(红-绿-重构),或需要集成测试时使用。

- Skill: `gongyijie85/tdd` (Agent Skill)
- Install (CLI): `npx skillmds@latest add gongyijie85/tdd`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gongyijie85/tdd/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: gongyijie85 (https://skillmd.com/u/gongyijie85)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/gongyijie85/tdd

---


# 测试驱动开发(Test-Driven Development)

TDD 就是 red → green(红 → 绿)循环。本技能是让这一循环产出值得保留的测试的参考:什么样的测试是好测试、测试放在哪里、有哪些反模式,以及循环的规则。每个小节在每一轮循环中都适用——在循环开始前和进行中查阅它们,而不是事后才看。

在探索代码库时,阅读 `CONTEXT.md`(如果存在),让测试名称和接口词汇与项目的领域语言保持一致,并尊重你所触及区域的 ADR。

## 什么是好的测试

测试通过公共接口验证行为,而不是实现细节。代码可以彻底改变;测试不应随之改变。好的测试读起来就像一份规格说明——"用户可以用有效的购物车完成结账"准确告诉你存在什么能力——而且它不在乎内部结构,所以能扛住重构。

示例参见 [tests.md](tests.md),mock 指南参见 [mocking.md](mocking.md)。

## Seam(接缝)——测试放在哪里

**seam(接缝)** 是你进行测试的公共边界:在不深入内部的情况下观察行为的接口。测试放在 seams 上,绝不针对内部实现。

**只在你预先约定的 seams 上测试。** 在编写任何测试之前,写下将要测试的 seams 并与用户确认。未经确认的 seam 上不写任何测试。你不可能测试所有东西——提前约定 seams,才能让测试精力落在关键路径和复杂逻辑上,而不是撒在每个边界情况上。

询问:"公共接口是什么,我们应该测试哪些 seam?"

当接口本身的形态存疑时——模块该有多深、seam 该放在哪里、接口应暴露什么——调用 skill tool,使用 "codebase-design" 获取相关词汇。它是 module、interface、depth、seam、adapter、leverage 和 locality 这些术语的共同来源,是一份供查阅的参考,而不是要运行的一次会话。

## 反模式

- **Implementation-coupled(实现耦合)**——mock 内部协作者、测试私有方法,或通过旁路通道验证(直接查询数据库而不是使用接口)。典型特征:重构时测试破裂,但行为并没有变化。
- **Tautological(同义反复)**——断言用与代码相同的方式重新计算期望值(`expect(add(a, b)).toBe(a + b)`、以同样方式手工推导出的 snapshot、断言常量等于自身),因此它凭构造就能通过,永远不可能与代码产生分歧。期望值必须来自独立的真值来源——已知正确的字面量、手算示例、spec。
- **Horizontal slicing(水平切片)**——先写完所有测试,再写全部实现。批量测试验证的是_想象中的_行为:你测试的是事物的_形状_而不是面向用户的行为,测试对真实变化不敏感,而且你在理解实现之前就锁定了测试结构。改为按 **vertical slices(垂直切片)** 工作——一个测试 → 一个实现 → 重复,每个测试都是一颗 **tracer bullet(曳光弹)**,对上一轮循环教给你的东西做出回应。

## 循环的规则

- **Red before green(先红后绿)。** 先写失败的测试,然后只写足以让它通过的代码。不要预想未来的测试,也不要添加投机性的功能。
- **One slice at a time(一次一个切片)。** 每轮循环一个 seam、一个测试、一个最小实现。
- **Refactoring is not part of the loop(重构不属于循环)。** 它属于 review 阶段(参见 `code-review` 技能),而不是 red → green 实现循环。

