TDD 工作流是一个面向 Expo 应用(iOS 和 Android)的测试驱动开发技能,强调红-绿-重构循环:先写一个引用需求的失败测试,再写使测试通过的最少代码,然后重构,最后将测试与代码一起提交。每个提交只包含一个行为。
主要能力与规则:
- 没有看到正确原因失败的测试(断言差异,而非模块缺失或语法错误),不写产品代码。
- 红色和绿色测试在同一提交中,每个提交只包含一个行为;不提交失败测试。
- 不修改现有断言来使测试通过;只有需求变更时,才通过 Spec-Change 尾注说明并修改期望。
- 禁止使用 skip、only、retry、快照、降低阈值、eslint-disable 或 --no-verify 等手段弱化测试。
- 在第一个测试中引用需求(来自 spec 或 issue),并记录在测试标题或注释中。
- 按层序构建:纯逻辑 → 持久化与迁移 → 服务(端口与假实现)→ stores 与模型 hook → 组件与屏幕 → 路由及其测试 → 端到端流程 → 截图矩阵。
- 纯逻辑需包含示例、fast-check 属性测试以及至少一个固定精确值,覆盖边界值及越界值。
- 测试必须确定性:不能使用 Math.random、Date.now、真实定时器、网络、locale 或时区;需注入假时钟和种子随机数生成器。
- 测试文件位置和命名有严格约定:单元测试放在 src/ 下的单元旁,Android 专属测试用 .android.test.ts(x),golden 测试用 *.golden.test.ts,Node API 测试放在 test/ 下,不在路由文件夹 src/app/ 中放置测试,不使用 tests/ 或 .spec.ts。
- 每个逻辑模块必须附带测试;只有 Jest 无法加载的薄原生封装可以以 // device-only: 标记开头并注明覆盖方式。
- 每类变更需提供证据:UI 变更需组件测试及 iOS 模拟器和 Android 模拟器上明暗主题、LTR/RTL(如支持)的截图,并与批准的设计基线比较。
工作流程:
- 从绿色状态开始:检查 git 状态、日志,记录基准提交,运行快速检查。
- 找到任务对应的需求,填写切片计划(行为一句话、首个测试标题、文件、证据)。
- 根据层序放置切片;若依赖的底层未测试,先构建底层。
- 编写一个失败测试,复制模板并替换占位符,运行 prettier 格式化,然后运行测试并阅读失败原因。
- 编写最少代码使测试通过,再添加下一个示例。
- 按职责重构,保持测试绿色。
- 运行快速检查和代码树检查脚本,修复所有失败项。
- 提交切片(测试和代码一起),提交前用 check-test-edits.mjs 检查暂存区,提交后用 --range 检查历史。
- 根据变更类型收集证据并报告。
定义完成条件:
- 每个新行为都有测试在代码之前因断言失败而被看到,失败记录在报告中。
- 每个提交包含一个行为及其测试和代码;没有有效 Spec-Change 尾注不修改现有断言。
- 纯逻辑有示例、属性和固定值;UI 有组件测试及两个平台的截图。
- npm run -s check:fast 通过(推送前运行 npm run verify)。
- check-test-edits.mjs 和 check-tests.mjs 均输出 RESULT: PASS。
反模式包括:先写代码再写测试、因模块缺失而“红”、修改断言来通过、用 skip 搁置测试、每个测试中写巨大对象字面量、快照组件树、在路由文件夹放测试、在 iOS 测试中设置 Platform.OS = 'android'、通过 UI 测试属性已证明的逻辑、一个提交包含多个行为。
该技能包含参考文档(tdd-loop.md、test-conventions.md、build-order.md、definition-of-done.md)、模板(logic.test.ts、component.test.tsx、contracts/tdd.json 等)、资产(slice-plan.md 等)、示例(slice-walkthrough.md)以及脚本(check-tests.mjs、check-test-edits.mjs)等文件,用于支持整个工作流。