# Tdd

> 测试驱动开发。当用户想以测试先行构建功能或修复 bug、提到 "red-green-refactor"，或想要集成测试时使用。

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

---


# 测试驱动开发（Test-Driven Development）

TDD 是红 → 绿的循环。本技能是让这个循环产出值得保留的测试的参考：好测试是什么、测试放在哪里、反模式有哪些、循环的规则是什么。每一节在每一个循环中都适用——在循环之前和之中查阅它们，而不是之后。

探索代码库时，读 `CONTEXT.md`（如果存在），让测试名称和接口词汇与项目的领域语言一致，并尊重你正在触碰的区域的 ADR。

## 好测试是什么

测试通过公共接口验证行为，而不是实现细节。代码可以彻底改变；测试不应该。好测试读起来像一份规格——"用户可以用有效购物车结账"精确地告诉你存在什么能力——而且因为它不关心内部结构，能在重构中存活。

示例见 [tests.md](tests.md)，mocking 指南见 [mocking.md](mocking.md)。

## 接缝——测试放在哪里

**接缝（seam）**是你测试所在的公共边界：在不伸手进内部的情况下观察行为的接口。测试住在接缝处，绝不对着内部。

**只在预先约定的接缝处测试。** 写任何测试之前，写下要测试的接缝并与用户确认。没有测试写在未经确认的接缝上。你不可能测试所有东西——提前约定接缝，正是让测试精力落在关键路径和复杂逻辑上、而不是每个边界情况上的方法。

问："公共接口是什么，我们应该测试哪些接缝？"

当接口的形态本身存疑时——模块该有多深、接缝该在哪里、接口应该暴露什么——调用 Skill 工具并传入 "codebase-design" 来获得词汇。它是 module、interface、depth、seam、adapter、leverage、locality 这些词的共享来源，是一份供查阅的参考，而不是要跑的一场会话。

## 反模式

- **与实现耦合（Implementation-coupled）** — mock 内部协作者、测试私有方法、或通过旁路渠道验证（查数据库而不是用接口）。识别信号：重构时行为没变，测试却挂了。
- **同义反复（Tautological）** — 断言用与代码相同的方式重新计算期望值（`expect(add(a, b)).toBe(a + b)`、以同样方式手工推导出的快照、断言常量等于自身），所以它构造性地通过，永远不可能与代码相左。期望值必须来自独立的真实来源——已知正确的字面量、手算的示例、规格。
- **水平切片（Horizontal slicing）** — 先写完所有测试，再写所有实现。成批的测试验证的是*想象出来的*行为：你测试的是事物的*形状*而不是面向用户的行为，测试对真实变化变得不敏感，而且你在理解实现之前就锁定了测试结构。改用**垂直切片**——一个测试 → 一个实现 → 重复，每个测试都是一颗**示踪子弹**，对上一循环教会你的东西作出回应。

## 循环的规则

- **先红后绿。** 先写会失败的测试，然后只写恰好能通过它的代码。不要预想未来的测试，也不要加投机性的功能。
- **一次一个切片。** 每个循环一个接缝、一个测试、一个最小实现。
- **重构不是循环的一部分。** 它属于审查阶段（见 `code-review` 技能），不属于红 → 绿实现循环。

