---
name: test-driven-development
description: "Red-Green-Refactor cycle, test pyramid (80/15/5), test sizes, DAMP over DRY. Invoke when implementing logic, fixing bugs, changing behavior, or when user says /test. | 红绿重构循环，测试金字塔(80/15/5)，测试尺寸，DAMP优于DRY。当实现逻辑、修复Bug、变更行为时，或用户说 /test 时触发。"
metadata:
  {
    "builtin_skill_version": "1.0",
    "xingzierai":
      {
        "emoji": "✅",
        "requires": {}
      }
  }
---
# Test-Driven Development

Red-Green-Refactor. Write tests that prove your code works.

## Overview

TDD is not about writing tests after—it's about writing tests that define "done". The cycle is:
1. **Red**: Write a failing test
2. **Green**: Write minimum code to pass
3. **Refactor**: Improve code while keeping tests green

Tests are proof, not afterthought. If it's not tested, it's broken.

## When to Use

**Activate this skill when:**
- User says `/test` or asks to "write tests" or "TDD"
- Implementing new logic or function
- Fixing a bug (write a test that reproduces the bug first)
- Changing existing behavior
- Before merging any code change

**Do not activate for:**
- Trivial one-liners
- Already well-tested legacy code
- Configuration changes

## Process

### Step 1: Write the Failing Test First

1. Identify the behavior you're implementing
2. Write a test that calls the code with known inputs
3. Assert the expected outputs
4. Run test -> it should **fail**

```python
def test_add_numbers():
    result = add(2, 3)
    assert result == 5
```

### Step 2: Write Minimum Code to Pass

1. Write the **simplest** code that makes test pass
2. Don't optimize yet
3. Don't add features
4. Just make the test green

### Step 3: Refactor

1. Make the code correct and clean
2. Keep tests green throughout
3. Use tests to verify refactoring didn't break anything

### Step 4: Test Pyramid

Follow the **80/15/5** rule:

| Level | Ratio | What | Speed |
|-------|-------|------|-------|
| Unit | 80% | Test functions/classes in isolation | Fast (<1ms) |
| Integration | 15% | Test component interactions | Medium (ms-s) |
| E2E | 5% | Test full user flows | Slow (s) |

### Step 5: Test Naming (DAMP over DRY)

**DAMP**: Descriptive And Meaningful Phrases

```python
def test_user_login_fails_with_invalid_password():
    ...
```

### Step 6: Test Sizes

| Size | Execution Time | Network | File I/O | Database |
|------|---------------|---------|----------|----------|
| Small | <10ms | No | No | No |
| Medium | <100ms | Local only | Local only | In-memory |
| Large | Unlimited | Allowed | Allowed | Allowed |

Prefer **small tests** that run in isolation.

## Anti-Patterns to Avoid

- **Happy path only**: Test failures too
- **Testing implementation**: Test behavior, not how it's done
- **Complex assertions**: One assertion per test is preferred
- **Shared state**: Tests should be independent
- **No mocking**: Mock external dependencies

## Rationalizations

| Excuse | Rebuttal |
|--------|----------|
| "Tests slow me down" | Tests catch bugs early. Debugging is slower. |
| "I'll add tests later" | Later never comes. Tests define done. |
| "It's just a small change" | Small changes break too. Test them. |
| "The code is obvious" | Code is obvious to the author. Tests are for others. |

## Red Flags

- No tests for new functionality
- Tests always passing (probably not testing anything)
- Tests depending on each other
- Mocking everything (no real behavior tested)
- Tests slower than 100ms (too integration-heavy)

## Verification

**Evidence that TDD is working:**

- [ ] Tests written before implementation (Red phase)
- [ ] All tests pass
- [ ] Test coverage for new code
- [ ] Tests are fast (<100ms)
- [ ] Tests are independent
- [ ] Descriptive test names (DAMP)
