Skip to content
cccskills
FreePublished on GitHub

tdd-workflow

用于需要以测试驱动开发、遵循“红—绿—重构”循环实现功能或修复缺陷的场景。必须先编写失败测试,再实现代码。

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md10.5 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

TDD Workflow - 测试驱动开发工作流

铁律

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

违反规则的信件就是违反规则的精神。

无例外:

  • 不保留为"参考"
  • 写测试时"不调整"
  • 不看它
  • 删除=删除

常见合理化

借口现实
"太简单不需要测试"简单代码也会坏。测试只需 30 秒
"我之后再测试"测试立即通过证明不了什么
"测试后达到相同目的"测试后="代码做什么?"测试前="代码应该做什么?"
"已经手动测试了"临时≠系统化。无记录,无法重新运行
"删除 X 小时工作是浪费"沉没成本谬误。保留未验证代码是技术债
"保留参考,先写测试"你会调整它。那是测试后。删除=删除

红色标志 - 停止并重新开始

  • 测试前有代码
  • "已经手动测试了"
  • "测试后达到相同目的"
  • "是精神而非仪式"
  • "只此一次"的合理化
  • "保留为参考"
  • 写测试时"不调整"

所有这些意味着:删除代码。用 TDD 重新开始。


核心理念

测试驱动开发(Test-Driven Development, TDD) 是一种先编写测试,再编写实现代码的开发方法。通过严格的 Red-Green-Refactor 循环,确保代码质量和可维护性。

TDD 循环

┌─────────────────────────────────────────────────────────┐
│  1. RED    : 编写失败的测试                              │
│  2. GREEN  : 编写最简单的代码使测试通过                   │
│  3. REFACTOR: 在测试保护下重构代码                       │
│  4. 重复循环                                            │
└─────────────────────────────────────────────────────────┘

何时使用本技能

在以下场景时激活:

  • 用户明确要求使用 TDD 或 测试驱动开发
  • 需要编写新功能或修复 Bug
  • 提到"测试"、"单元测试"、"测试覆盖率"
  • 需要确保代码质量
  • 重构现有代码(先补充测试)

TDD 工作流程

步骤 1:理解需求

在开始编码前,明确:

  • 功能需求:这个功能要做什么?
  • 验收标准:如何判断功能正确?
  • 边界条件:有哪些特殊情况?
  • 错误处理:异常情况如何处理?

步骤 2:编写失败测试(RED)

测试先行原则:

  1. 先写测试,不写实现
  2. 运行测试,确认失败(证明测试有效)
  3. 阅读错误信息,理解预期

测试命名规范(AAA 模式):

# Should_预期行为_When_测试条件
def should_return_user_when_id_exists():
    # Arrange(准备)
    user_id = 123
    expected_user = User(id=123, name="Alice")

    # Act(执行)
    result = user_service.get_by_id(user_id)

    # Assert(断言)
    assert result.id == expected_user.id
    assert result.name == expected_user.name

步骤 3:最小化实现(GREEN)

最简单的可工作代码:

  • 只写足够使测试通过的代码
  • 不追求完美,追求通过
  • 硬编码可以接受(第一步)
# 最初版本 - 硬编码也可以
def get_by_id(user_id):
    if user_id == 123:
        return User(id=123, name="Alice")
    return None

步骤 4:运行测试确认通过

# 运行测试
pytest tests/test_user_service.py -v

# 期望输出
✅ should_return_user_when_id_exists PASSED

步骤 5:重构代码(REFACTOR)

在测试保护下优化:

  • 消除重复
  • 提取方法
  • 改善命名
  • 优化结构
# 重构后版本
def get_by_id(user_id):
    return _user_repository.find_by_id(user_id)

步骤 6:重复循环

每个功能点重复上述步骤,直到功能完整。


测试质量标准

必须遵守的规则

  • ✅ 测试覆盖率 ≥ 80%
  • ✅ 每个测试用例独立(不依赖其他测试)
  • ✅ 测试可重复(多次运行结果一致)
  • ✅ 测试命名清晰(描述意图)
  • ✅ 遵循 AAA 模式(Arrange-Act-Assert)

禁止的反模式

  • ❌ 伪测试:测试代码没有断言
  • ❌ 万能测试:一个测试验证太多东西
  • ❌ 测试内部实现:应该测试行为,不是实现细节
  • ❌ 脆弱测试:依赖外部状态(时间、随机数等)

TDD 最佳实践

1. 小步前进

  • 一次只写一个测试
  • 一次只实现一个功能点
  • 频繁运行测试(每 1-2 分钟)

2. 测试隔离

# 好的示例 - 使用 fixtures
@pytest.fixture
def clean_database():
    db.reset()
    yield
    db.cleanup()

def test_create_user(clean_database):
    user = user_service.create("Alice")
    assert user.name == "Alice"

3. 测试边界条件

def test_get_by_id():
    # 正常情况
    assert get_user(1) is not None

    # 边界条件
    assert get_user(0) is None
    assert get_user(-1) is None
    assert get_user(999999) is None

4. 测试异常情况

def test_create_user_with_duplicate_email():
    with pytest.raises(DuplicateEmailError):
        user_service.create("alice@example.com")
        user_service.create("alice@example.com")

不同语言的 TDD 示例

Python(pytest)

# 测试
def should_calculate_total_price():
    cart = ShoppingCart()
    cart.add_item(Item(name="Book", price=10))
    cart.add_item(Item(name="Pen", price=5))

    assert cart.total_price() == 15

# 实现
class ShoppingCart:
    def __init__(self):
        self.items = []

    def add_item(self, item):
        self.items.append(item)

    def total_price(self):
        return sum(item.price for item in self.items)

JavaScript(Jest)

// 测试
test('should calculate total price', () => {
  const cart = new ShoppingCart();
  cart.addItem({ name: 'Book', price: 10 });
  cart.addItem({ name: 'Pen', price: 5 });

  expect(cart.totalPrice()).toBe(15);
});

// 实现
class ShoppingCart {
  constructor() {
    this.items = [];
  }

  addItem(item) {
    this.items.push(item);
  }

  totalPrice() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}

TypeScript(Jest)

// 测试
test('should calculate total price', () => {
  const cart = new ShoppingCart();
  cart.addItem({ name: 'Book', price: 10 });
  cart.addItem({ name: 'Pen', price: 5 });

  expect(cart.totalPrice()).toBe(15);
});

// 实现
interface Item {
  name: string;
  price: number;
}

class ShoppingCart {
  private items: Item[] = [];

  addItem(item: Item): void {
    this.items.push(item);
  }

  totalPrice(): number {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}

常见问题

Q1: 是否需要 100% 测试覆盖率?

A: 不一定。80-90% 是合理目标。以下情况可以例外:

  • UI 组件(优先用 E2E 测试)
  • 简单的 getter/setter
  • 第三方库的封装

Q2: 如何测试私有方法?

A: 不要直接测试私有方法。应该通过公共接口测试其行为。如果私有方法太复杂,考虑提取到独立的类。

Q3: TDD 会降低开发速度吗?

A: 短期可能稍慢,但长期来看:

  • 减少调试时间
  • 减少回归 Bug
  • 提高代码可维护性
  • 整体效率提升 30-50%

Q4: 什么时候不适合 TDD?

A:

  • 探索性原型(POC)
  • UI 设计探索
  • 紧急热修复(但仍应事后补充测试)

验证清单

完成 TDD 开发后,检查:

  • 所有测试通过
  • 测试覆盖率 ≥ 80%
  • 每个测试用例独立且可重复
  • 测试命名清晰(Should_ExpectedBehavior_When_StateUnderTest)
  • 遵循 AAA 模式
  • 无伪测试(所有测试都有断言)
  • 边界条件已测试
  • 异常情况已测试

相关参考

约束

<!-- BEGIN COMMON CONSTRAINTS --> <!-- Source-Hash: sha256:15120201e9e0c7569517261d57ecefb63ac279c26ed13876f8e95b6dc35854d3 --> <!-- Template-ID: skill-common-constraints; Template-Version: 1; Sync-Policy: exact-block -->

公共硬约束

本块由 docs/templates/skill-common-constraints.md 统一维护;每个 SKILL.md 的 ## 约束 必须逐字同步本块,不得在副本中改写公共规则。

  • 任务需要落盘时,使用唯一的 ./.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/ 根目录;共享材料放入 shared/,Skill 专属材料放入该 Skill 的 input/、output/、log/。
  • 正式交付物、源代码和正式计划按项目约定保存,不写入任务工作区;未经授权不覆盖、删除、迁移或远程写入。
  • 项目维护变更检查 BAC 可用性并记录需求、AI 产出、工具结果、文件改动和验证摘要;BAC 只做过程审计,不替代署名、责任或合规判断。
  • 不记录 API Key、访问令牌、密码、Cookie、环境/凭据文件、私有 Prompt、身份信息、本地用户名、主机名或不必要的大体积原始数据。
  • 文件路径必须规范化并限制在授权项目范围内;外部 URL、子进程和网络访问遵循最小权限,防止路径遍历、SSRF 和命令注入。
  • Skill 版本唯一记录在自身 config.yaml:skill_info.version;公开 API、协议、目录或配置变更同步文档与 CHANGELOG.md。
  • bensz-collect-bugs 是一个 Agent Skill;仅将 Bensz Agent Skill 或 Bensz 基础设施本身的设计缺陷交给它。先脱敏写入 ~/.bensz-skills/bugs/,当前任务不中断,只有用户明确要求才公开上报,禁止直接修改用户已安装的 Skill 源码。
<!-- End of canonical common constraints. --> <!-- END COMMON CONSTRAINTS -->

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

当用户明确要求转换、修改或批量转换图片格式时使用。支持常见本地或网络图片输入与常见目标格式输出。⚠️ 不适用:仅调整尺寸/裁剪、查看图片信息,或没有明确格式转换意图。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

根据用户描述生成高质量绘图 prompt,并按通用、roadmap、schematic 模式通过 BenszAPI 直接完成 gpt-image-2.5-flare、gpt-image-2.5-sunburst、gpt-image-2 或 Nano Banana/Gemini 出图、编辑和多轮迭代;这是自包含的图片生成工作流,选中后不得调用或依赖 imagegen,除非用户明确要求同时使用 imagegen。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

当用户明确要求测试代码、代码审查或代码自检时使用。系统化发现并验证代码问题。⚠️ 不适用:用户只是想实现或优化功能、询问代码问题,或没有明确测试意图。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

当用户明确要求“测试项目”、 “运行 auto-test-project”或“进行项目级测试”时使用。对完整项目执行多轮 A 轮批判性测试与 B 轮质量检查,发现、记录、修复并验证问题。⚠️ 不适用:用户只是想优化功能、询问项目问题,或没有明确测试意图。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

当用户明确要求测试 Skill、运行 auto-test 或对 Skill 进行批判性测试时使用。系统化发现、记录并验证 Skill 问题。⚠️ 不适用:用户只是想开发或优化 Skill,或没有明确测试意图。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

当用户明确要求使用 awesome-code、进行多代理协作或需要复杂任务规划时使用。它负责拆解任务、选择专业角色、设置门禁并审查结果;所有 Agent 的创建、隔离、串行或并行执行都必须交给 `parallel-vibe`。⚠️ 不适用:用户只需单一角色完成简单修改或咨询,或未表达多代理协作意图。

The English summary is being prepared. Showing the original description.

huangwb8/skills50Updated Oct 18, 2026

See all skills by huangwb8

Report a problem with this skill