--- name: dev-tdd description: 开发流程 - TDD 测试先行阶段,基于设计文档生成测试骨架,实现测试驱动开发 --- # TDD 测试先行 > 开发流程第四阶段:基于设计文档生成测试骨架,先写测试再写实现,确保验收标准可量化。 ## 调用方式 `/dev-tdd`,也可说"生成测试用例"或"TDD"。 ## 产出目录 `docs/test-cases/`(测试用例设计文档) 项目源码中的测试文件(`.test.ts` / `.spec.ts` / `_test.py` 等) ## 执行流程 ### Checklist - [ ] 前置检查:读取需求和设计文档 - [ ] 检测项目测试框架 - [ ] 按模块识别测试点 - [ ] 生成测试用例文档 - [ ] 生成测试代码骨架(空实现 / 先失败) - [ ] 验证测试可运行且初始状态为失败 - [ ] 用户确认 ### 1. 前置检查 - 读取 `docs/requirements/` 需求文档 - 读取 `docs/design/` 设计文档(模块划分、接口定义、数据模型) - 如果设计文档不存在,提示用户先运行 `/dev-design`(可选择跳过,基于需求直接生成) - 展示设计摘要,确认测试生成范围 ### 2. 检测项目测试框架 自动检测项目使用的测试框架: | 语言 | 检测方式 | 常用框架 | |------|---------|---------| | JavaScript/TypeScript | package.json devDependencies | jest, vitest, mocha, playwright | | Python | pyproject.toml / requirements.txt | pytest, unittest | | Java | pom.xml / build.gradle | JUnit, TestNG | | Go | go.mod | testing, testify | | Rust | Cargo.toml | 内置 test | 如果没有检测到测试框架: - 询问用户是否安装(推荐 Vitest 或 Jest 用于 JS/TS,pytest 用于 Python) - 如用户拒绝,生成 `docs/test-cases/` 下的纯文本测试用例文档,不生成代码 ### 3. 按模块识别测试点 基于设计文档的模块划分,为每个模块识别测试点: **每个模块的测试点维度:** - **正常路径**:标准输入下的预期输出 - **边界情况**:空值、最大值、最小值、空数组等 - **错误路径**:异常输入、权限不足、网络失败等 - **状态转换**:涉及状态机的模块,各状态转换路径 ### 4. 生成测试用例文档 为每个模块生成测试用例设计文档,保存到 `docs/test-cases/`: ```markdown # 测试用例设计:<模块名> > 对应设计:docs/design/xxx.md > 对应模块:模块 A ## 测试用例 1:正常路径 - [简短描述] **目标**:验证标准场景下的正确行为 **输入**:[具体值或描述] **预期输出**:[具体值或描述] **涉及接口**:[函数/端点名] **优先级**:高 ## 测试用例 2:边界情况 - [简短描述] **目标**:验证边界输入的处理 **输入**:[边界值] **预期输出**:[预期行为] **优先级**:中 ## 测试用例 3:错误路径 - [简短描述] **目标**:验证异常情况的处理 **输入**:[异常输入] **预期输出**:[错误码/异常类型] **优先级**:中 ``` ### 5. 生成测试代码骨架 基于检测到的测试框架,生成实际的测试代码文件: **原则:** - 每个测试用例对应一个测试函数 - 测试函数名清晰描述场景:`should_xxx_when_xxx` - 导入被测模块(根据设计文档中的接口定义) - 使用 `todo()` 或 `skip()` 标记尚未实现的测试,或先写失败的断言 - 不编写被测模块的实现代码 **示例(Vitest / TypeScript):** ```typescript // src/modules/user/user.service.test.ts import { describe, it, expect } from 'vitest' import { UserService } from './user.service' describe('UserService', () => { describe('创建用户', () => { it('should create user with valid input', () => { // TODO: 实现测试 // const service = new UserService() // const result = service.create({ name: '张三', email: 'zs@example.com' }) // expect(result.name).toBe('张三') expect(true).toBe(false) // 初始状态:失败 }) it('should reject empty name', () => { // TODO: 实现测试 expect(true).toBe(false) // 初始状态:失败 }) }) }) ``` ### 6. 验证测试可运行且失败 生成测试后: - 运行测试框架(如 `npm test` / `pytest`) - 确认测试可以被识别并执行 - 确认测试当前状态为**失败**(红) - 如测试无法运行,修复配置问题(路径、导入、框架设置等) ### 7. 用户确认 - 展示生成的测试用例文档摘要 - 展示测试代码骨架的关键部分 - 展示测试运行结果(确认是失败的) - 询问用户是否满意,或需要补充/修改测试场景 - 修改后循环直到确认 ## 流转规则 生成完成后,提示下一步: - `/dev-plan` — 将开发工作拆解为步骤(推荐) - `/dev-develop` — 直接进入开发,让测试变绿 ## 关键行为 - 测试用例必须能追溯到设计文档中的接口定义 - 测试初始状态必须为失败(红),不允许一开始就通过 - 不编写被测模块的实现代码,只写测试 - 测试函数名使用描述性语言,不依赖注释解释场景 - 如果设计文档中的接口不明确,先回到 `/dev-design` 澄清 ## TDD 原则提醒 1. **红**:先写一个失败的测试 2. **绿**:写最小代码让测试通过 3. **重构**:优化代码,保持测试通过 本阶段只负责第 1 步(红)。第 2-3 步在 `/dev-develop` 中完成。