基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/zouyangxiaohao111/javaclawbot --skill test-driven-development命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
基于浏览器的视觉头脑风暴伴侣,专为'反 AI 味'设计而生的设计 intelligence。融合 99 UX 准则 + 71 品牌 craft_notes + 人文与情感原则,让 mockup 一眼有人味儿。**前置依赖:必须加载 [brainstorming]**
| name | test-driven-development |
| description | 在实现任何功能或修复 bug 之前,在编写实现代码之前使用 |
先写测试。看着它失败。编写最小代码使其通过。
**核心原则:**如果你没有看着测试失败,你就不知道它是否测试了正确的东西。
违反规则的字面意思就是违反规则的精神。
总是:
例外情况(询问你的合作伙伴):
在想"就这一次跳过 TDD"?停下来。那是合理化。
没有先失败的测试,就不能写生产代码
在测试之前写代码?删除它。重新开始。
没有例外:
从测试重新实现。就这样。
digraph tdd_cycle {
rankdir=LR;
red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"];
verify_red [label="Verify fails\ncorrectly", shape=diamond];
green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"];
verify_green [label="Verify passes\nAll green", shape=diamond];
refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"];
next [label="Next", shape=ellipse];
red -> verify_red;
verify_red -> green [label="yes"];
verify_red -> red [label="wrong\nfailure"];
green -> verify_green;
verify_green -> refactor [label="yes"];
verify_green -> green [label="no"];
refactor -> verify_green [label="stay\ngreen"];
verify_green -> next;
next -> red;
}
编写一个最小测试来展示应该发生什么。
```typescript test('retries failed operations 3 times', async () => { let attempts = 0; const operation = () => { attempts++; if (attempts < 3) throw new Error('fail'); return 'success'; };const result = await retryOperation(operation);
expect(result).toBe('success'); expect(attempts).toBe(3); });
清晰的名称,测试真实行为,一件事
</Good>
<Bad>
```typescript
test('retry works', async () => {
const mock = jest.fn()
.mockRejectedValueOnce(new Error())
.mockRejectedValueOnce(new Error())
.mockResolvedValueOnce('success');
await retryOperation(mock);
expect(mock).toHaveBeenCalledTimes(3);
});
模糊的名称,测试的是 mock 而不是代码
要求:
必须做。永远不要跳过。
npm test path/to/test.test.ts
确认:
**测试通过了?**你在测试现有行为。修复测试。
**测试报错了?**修复错误,重新运行直到正确失败。
编写最简单的代码来通过测试。
```typescript async function retryOperation(fn: () => Promise): Promise { for (let i = 0; i < 3; i++) { try { return await fn(); } catch (e) { if (i === 2) throw e; } } throw new Error('unreachable'); } ``` 刚好足够通过 ```typescript async function retryOperation( fn: () => Promise, options?: { maxRetries?: number; backoff?: 'linear' | 'exponential'; onRetry?: (attempt: number) => void; } ): Promise { // YAGNI (你不会需要它) } ``` 过度工程化不要添加功能、重构其他代码或"改进"超出测试范围的内容。
必须做。
npm test path/to/test.test.ts
确认:
**测试失败了?**修复代码,不是测试。
**其他测试失败了?**立即修复。
只在变绿之后:
保持测试绿色。不要添加行为。
为下一个功能编写下一个失败的测试。
| 品质 | 好 | 坏 |
|---|---|---|
| 最小化 | 一件事。名称中有"和"?拆分它。 | test('validates email and domain and whitespace') |
| 清晰 | 名称描述行为 | test('test1') |
| 展示意图 | 演示期望的 API | 模糊了代码应该做什么 |
"我会在之后写测试来验证它有效"
代码之后写的测试会立即通过。立即通过证明不了什么:
测试优先迫使你看到测试失败,证明它确实测试了某些东西。
"我已经手动测试了所有边缘情况"
手动测试是临时的。你认为自己测试了一切,但是:
自动化测试是系统化的。它们每次都以相同的方式运行。
"删除 X 小时的工作是浪费"
沉没成本谬误。时间已经过去了。你现在的选择:
"浪费"是保留你无法信任的代码。没有真正测试的工作代码是技术债务。
"TDD 是教条的,务实意味着适应"
TDD 就是务实的:
"务实"的捷径 = 在生产环境中调试 = 更慢。
"之后的测试达到相同的目标 - 是精神不是仪式"
不。之后测试回答"这做什么?"测试优先回答"这应该做什么?"
之后测试受你的实现偏见影响。你测试你构建的东西,而不是需求。你验证记住的边缘情况,而不是发现的。
测试优先在实现之前强制发现边缘情况。之后测试验证你记住了一切(你没有)。
之后 30 分钟的测试 ≠ TDD。你获得了覆盖率,失去了测试有效的证明。
| 借口 | 现实 |
|---|---|
| "太简单不需要测试" | 简单代码也会出错。测试只需 30 秒。 |
| "我会在之后测试" | 立即通过的测试证明不了什么。 |
| "之后的测试达到相同目标" | 之后测试 = "这做什么?"测试优先 = "这应该做什么?" |
| "已经手动测试了" | 临时的 ≠ 系统化的。没有记录,无法重新运行。 |
| "删除 X 小时是浪费" | 沉没成本谬误。保留未验证的代码是技术债务。 |
| "保留作为参考,先写测试" | 你会调整它。那是之后测试。删除意味着删除。 |
| "需要先探索" | 可以。扔掉探索,用 TDD 开始。 |
| "测试困难 = 设计不清楚" | 听测试的。难测试 = 难使用。 |
| "TDD 会让我变慢" | TDD 比调试快。务实 = 测试优先。 |
| "手动测试更快" | 手动不能证明边缘情况。每次更改你都要重新测试。 |
| "现有代码没有测试" | 你在改进它。为现有代码添加测试。 |
所有这些都意味着:删除代码。用 TDD 重新开始。
**Bug:**空邮箱被接受
RED
test('rejects empty email', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('Email required');
});
验证 RED
$ npm test
FAIL: expected 'Email required', got undefined
GREEN
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: 'Email required' };
}
// ...
}
验证 GREEN
$ npm test
PASS
REFACTOR 如果需要,为多个字段提取验证。
在标记工作完成之前:
无法勾选所有框?你跳过了 TDD。重新开始。
| 问题 | 解决方案 |
|---|---|
| 不知道如何测试 | 编写期望的 API。先写断言。询问你的合作伙伴。 |
| 测试太复杂 | 设计太复杂。简化接口。 |
| 必须模拟一切 | 代码耦合太紧。使用依赖注入。 |
| 测试设置巨大 | 提取辅助函数。仍然复杂?简化设计。 |
发现 bug?编写失败的测试来复现它。遵循 TDD 循环。测试证明修复并防止回归。
永远不要没有测试就修复 bug。
当添加 mock 或测试工具时,阅读 @testing-anti-patterns.md 以避免常见陷阱:
生产代码 → 测试存在且先失败
否则 → 不是 TDD
没有你的合作伙伴的许可,没有例外。