关于 tdd-workflows-tdd-red
用于 TDD 红阶段的技能,通过生成应当失败的测试来明确预期行为,适合开始实现新功能或补充边界情况覆盖的开发者。它要求验证失败源于缺失行为而非测试配置错误。
主要功能
- 01根据预期行为生成失败测试
- 02覆盖边界情况与错误处理
- 03使用项目现有测试框架
- 04检查失败原因与诊断信息
- 05提供测试运行和验证步骤
适用场景
- 01为新功能定义预期行为
- 02在实现前覆盖边界情况
- 03验证缺失行为导致测试失败
- 04隔离测试数据并避免外部依赖
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill tdd-workflows-tdd-red安装后在 Claude Code 中输入/tdd-workflows-tdd-red确认已加载。
详细介绍
编写全面的失败测试,遵循 TDD 红灯阶段原则。
[扩展思考:使用 test-automator agent 生成能够正确定义预期行为的失败测试。]
适用场景
- 开始新行为的 TDD 红灯阶段
- 需要能够描述预期行为的失败测试
- 希望在实现前覆盖边界情况
不适用场景
- 处于绿灯或重构阶段
- 只需要性能基准测试
- 测试必须针对生产系统运行
说明
- 确定行为、约束和边界情况。
- 生成能够定义预期结果的失败测试。
- 确保失败是由缺少行为导致的,而不是设置错误。
- 说明如何运行测试并验证失败。
安全
- 隔离测试数据,避免使用生产环境。
- 在红灯阶段避免不稳定的外部依赖。
角色
使用当前项目的测试框架和可用工具。上游的 Task/subagent 类型因宿主而异,且未随附;这并不授权委派任务。如果没有获得授权且类型匹配的 Agent,请直接编写测试。
提示词模板
"为以下内容生成全面的失败测试:$ARGUMENTS
核心要求
-
测试结构
- 使用适合框架的设置方式(Jest/pytest/JUnit/Go/RSpec)
- 遵循 Arrange-Act-Assert 模式
- 使用 should_X_when_Y 命名约定
- 使用彼此独立的固定数据,不存在相互依赖
-
行为覆盖
- 成功路径场景
- 边界情况(空值、null、边界值)
- 错误处理和异常
- 并发访问(如适用)
-
失败验证
- 运行时测试必须失败
- 失败原因必须正确(而非语法/导入错误)
- 提供有意义的诊断错误消息
- 不出现级联失败
-
测试类别
- 单元:隔离的组件行为
- 集成:组件交互
- 契约:API/接口契约
- 属性:数学不变量
框架模式
JavaScript/TypeScript (Jest/Vitest)
- 使用
vi.fn()或jest.fn()模拟依赖 - React 组件使用
@testing-library - 属性测试使用
fast-check
Python (pytest)
- 使用适当作用域的固定数据
- 对多个测试用例进行参数化
- 基于属性的测试使用 Hypothesis
Go
- 使用表驱动测试和子测试
- 使用
t.Parallel()并行执行 - 使用
testify/assert编写更简洁的断言
Ruby (RSpec)
- 使用
let延迟加载,使用let!即时加载 - 使用上下文描述不同场景
- 使用共享示例覆盖常见行为
质量检查清单
- 测试名称清晰易读,能够说明意图
- 每个测试只验证一种行为
- 不泄露实现细节
- 使用有意义的测试数据(而非 'foo'/'bar')
- 测试可作为动态文档
应避免的反模式
- 测试立即通过
- 测试实现而非行为
- 设置代码过于复杂
- 一个测试承担多个职责
- 测试与具体实现细节绑定,导致脆弱
边界情况类别
- Null/空值:undefined、null、空字符串/数组/对象
- 边界:最小/最大值、单个元素、容量限制
- 特殊情况:Unicode、空白字符、特殊字符
- 状态:无效转换、并发修改
- 错误:网络故障、超时、权限
输出要求
- 提供包含导入语句的完整测试文件
- 说明测试目的
- 提供运行测试并验证失败的命令
- 指标:测试数量、覆盖范围
- 绿灯阶段的后续步骤"
验证
生成后:
- 运行测试,确认测试失败
- 验证失败消息是否有帮助
- 检查测试是否彼此独立
- 确保覆盖全面
示例(最简)
// 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: '[email protected]', passwordHash: 'hashed' };
mockUserRepo.findByEmail.mockResolvedValue(user);
const result = await authService.authenticate('[email protected]', '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('[email protected]', 'pass');
expect(result.success).toBe(false);
expect(result.error).toBe('INVALID_CREDENTIALS');
});
});
测试要求:$ARGUMENTS
限制
- 仅当任务明确符合上述范围时,才使用此技能。
- 不要将输出视为特定环境验证、测试或专家评审的替代品。
- 如果缺少必需的输入、权限、安全边界或成功标准,请停止并请求澄清。
评论
支持 Markdown