tdd-workflows-tdd-red
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWrite comprehensive failing tests following TDD red phase principles.
[Extended thinking: Generates failing tests that properly define expected behavior using test-automator agent.]
遵循TDD红阶段原则编写全面的失败测试。
[拓展思考:利用test-automator Agent生成能准确定义预期行为的失败测试。]
Use this skill when
适用场景
- Starting the TDD red phase for new behavior
- You need failing tests that capture expected behavior
- You want edge case coverage before implementation
- 为新功能启动TDD红阶段时
- 需要能体现预期行为的失败测试时
- 希望在实现前覆盖边缘情况时
Do not use this skill when
不适用场景
- You are in the green or refactor phase
- You only need performance benchmarks
- Tests must run against production systems
- 处于TDD绿阶段或重构阶段时
- 仅需要性能基准测试时
- 测试必须在生产环境运行时
Instructions
操作步骤
- Identify behaviors, constraints, and edge cases.
- Generate failing tests that define expected outcomes.
- Ensure failures are due to missing behavior, not setup errors.
- Document how to run tests and verify failures.
- 识别功能行为、约束条件和边缘情况。
- 生成能定义预期结果的失败测试。
- 确保测试失败是因为功能未实现,而非配置错误。
- 记录如何运行测试并验证失败结果。
Safety
注意事项
- Keep test data isolated and avoid production environments.
- Avoid flaky external dependencies in the red phase.
- 保持测试数据隔离,避免涉及生产环境。
- 在红阶段避免依赖不稳定的外部服务。
Role
角色定位
Generate failing tests using Task tool with subagent_type="unit-testing::test-automator".
使用Task工具,指定subagent_type="unit-testing::test-automator"来生成失败测试。
Prompt Template
提示词模板
"Generate comprehensive FAILING tests for: $ARGUMENTS
"为以下内容生成全面的失败测试:$ARGUMENTS
Core Requirements
核心要求
-
Test Structure
- Framework-appropriate setup (Jest/pytest/JUnit/Go/RSpec)
- Arrange-Act-Assert pattern
- should_X_when_Y naming convention
- Isolated fixtures with no interdependencies
-
Behavior Coverage
- Happy path scenarios
- Edge cases (empty, null, boundary values)
- Error handling and exceptions
- Concurrent access (if applicable)
-
Failure Verification
- Tests MUST fail when run
- Failures for RIGHT reasons (not syntax/import errors)
- Meaningful diagnostic error messages
- No cascading failures
-
Test Categories
- Unit: Isolated component behavior
- Integration: Component interaction
- Contract: API/interface contracts
- Property: Mathematical invariants
-
测试结构
- 适配对应测试框架的配置(Jest/pytest/JUnit/Go/RSpec)
- 遵循Arrange-Act-Assert模式
- 使用should_X_when_Y的命名规范
- 独立的测试夹具,无相互依赖
-
行为覆盖
- 正常流程场景
- 边缘情况(空值、Null、边界值)
- 错误处理与异常场景
- 并发访问(如适用)
-
失败验证
- 测试运行时必须失败
- 失败原因正确(非语法/导入错误)
- 有意义的诊断错误信息
- 无连锁失败
-
测试分类
- 单元测试:独立组件的行为
- 集成测试:组件间的交互
- 契约测试:API/接口契约
- 属性测试:数学不变量验证
Framework Patterns
框架模式
JavaScript/TypeScript (Jest/Vitest)
- Mock dependencies with or
vi.fn()jest.fn() - Use for React components
@testing-library - Property tests with
fast-check
Python (pytest)
- Fixtures with appropriate scopes
- Parametrize for multiple test cases
- Hypothesis for property-based tests
Go
- Table-driven tests with subtests
- for parallel execution
t.Parallel() - Use for cleaner assertions
testify/assert
Ruby (RSpec)
- for lazy loading,
letfor eagerlet! - Contexts for different scenarios
- Shared examples for common behavior
JavaScript/TypeScript (Jest/Vitest)
- 使用或
vi.fn()模拟依赖jest.fn() - 针对React组件使用
@testing-library - 使用进行属性测试
fast-check
Python (pytest)
- 使用对应作用域的测试夹具(fixtures)
- 用参数化实现多测试用例
- 使用Hypothesis进行属性测试
Go
- 采用表格驱动测试与子测试
- 使用实现并行执行
t.Parallel() - 用简化断言
testify/assert
Ruby (RSpec)
- 用于延迟加载,
let用于立即加载let! - 用Context区分不同场景
- 共享示例实现通用行为复用
Quality Checklist
质量检查清单
- Readable test names documenting intent
- One behavior per test
- No implementation leakage
- Meaningful test data (not 'foo'/'bar')
- Tests serve as living documentation
- 测试名称清晰易懂,能体现测试意图
- 每个测试仅验证一个行为
- 不泄露实现细节
- 使用有意义的测试数据(而非'foo'/'bar'这类占位符)
- 测试可作为活文档
Anti-Patterns to Avoid
需避免的反模式
- Tests passing immediately
- Testing implementation vs behavior
- Complex setup code
- Multiple responsibilities per test
- Brittle tests tied to specifics
- 测试立即通过
- 测试实现细节而非功能行为
- 复杂的配置代码
- 单个测试承担多个职责
- 与具体实现强耦合的脆弱测试
Edge Case Categories
边缘情况分类
- Null/Empty: undefined, null, empty string/array/object
- Boundaries: min/max values, single element, capacity limits
- Special Cases: Unicode, whitespace, special characters
- State: Invalid transitions, concurrent modifications
- Errors: Network failures, timeouts, permissions
- 空值/空对象:undefined、null、空字符串/数组/对象
- 边界值:最小/最大值、单元素、容量限制
- 特殊场景:Unicode字符、空白字符、特殊符号
- 状态相关:无效状态转换、并发修改
- 错误场景:网络故障、超时、权限问题
Output Requirements
输出要求
- Complete test files with imports
- Documentation of test purpose
- Commands to run and verify failures
- Metrics: test count, coverage areas
- Next steps for green phase"
- 包含导入语句的完整测试文件
- 测试目的说明文档
- 运行测试并验证失败的命令
- 指标:测试数量、覆盖范围
- 绿阶段的后续步骤"
Validation
验证步骤
After generation:
- Run tests - confirm they fail
- Verify helpful failure messages
- Check test independence
- Ensure comprehensive coverage
生成测试后:
- 运行测试 - 确认测试失败
- 验证错误信息是否有帮助
- 检查测试是否相互独立
- 确保覆盖全面
Example (Minimal)
示例(极简版)
typescript
// auth.service.test.ts
describe('AuthService', () => {
let authService: AuthService;
let mockUserRepo: jest.Mocked<UserRepository>;
beforeEach(() => {
mockUserRepo = { findByEmail: jest.fn() } as any;
authService = new AuthService(mockUserRepo);
});
it('should_return_token_when_valid_credentials', async () => {
const user = { id: '1', email: 'test@example.com', passwordHash: 'hashed' };
mockUserRepo.findByEmail.mockResolvedValue(user);
const result = await authService.authenticate('test@example.com', 'pass');
expect(result.success).toBe(true);
expect(result.token).toBeDefined();
});
it('should_fail_when_user_not_found', async () => {
mockUserRepo.findByEmail.mockResolvedValue(null);
const result = await authService.authenticate('none@example.com', 'pass');
expect(result.success).toBe(false);
expect(result.error).toBe('INVALID_CREDENTIALS');
});
});Test requirements: $ARGUMENTS
typescript
// auth.service.test.ts
describe('AuthService', () => {
let authService: AuthService;
let mockUserRepo: jest.Mocked<UserRepository>;
beforeEach(() => {
mockUserRepo = { findByEmail: jest.fn() } as any;
authService = new AuthService(mockUserRepo);
});
it('should_return_token_when_valid_credentials', async () => {
const user = { id: '1', email: 'test@example.com', passwordHash: 'hashed' };
mockUserRepo.findByEmail.mockResolvedValue(user);
const result = await authService.authenticate('test@example.com', 'pass');
expect(result.success).toBe(true);
expect(result.token).toBeDefined();
});
it('should_fail_when_user_not_found', async () => {
mockUserRepo.findByEmail.mockResolvedValue(null);
const result = await authService.authenticate('none@example.com', 'pass');
expect(result.success).toBe(false);
expect(result.error).toBe('INVALID_CREDENTIALS');
});
});测试需求:$ARGUMENTS