feat: adding new skills, including testing patterns and methodologies, along with bundled resources for better usability.

This commit is contained in:
duthaho
2026-03-30 12:18:00 +07:00
parent 0ff5ae4082
commit 7fa9a48c6c
89 changed files with 25808 additions and 923 deletions
@@ -1,9 +1,11 @@
---
name: test-driven-development
description: >
Trigger this skill whenever writing new features, fixing bugs, or changing any behavior in production code. Activate for keywords like "implement", "add feature", "fix bug", "write code", "build", "create endpoint", "add functionality", or any task that will result in production code changes. Also trigger when the user asks to refactor existing code, when tests need to be written, or when someone says "TDD". This skill should be the default for ALL implementation work -- no production code without a failing test first.
---
# Test-Driven Development (TDD)
## Description
Strict test-driven development methodology requiring tests before implementation. The fundamental practice: "If you didn't watch the test fail, you don't know if it tests the right thing."
## When to Use
- New feature development
@@ -11,11 +13,11 @@ Strict test-driven development methodology requiring tests before implementation
- Refactoring (ensure tests exist before changing)
- Any behavior change
## When NOT to Use (Requires Explicit Approval)
## When NOT to Use
- Throwaway prototypes
- Generated/scaffolded code
- Pure configuration changes
- Prototyping or throwaway code with explicit user approval to skip tests
- Configuration-only changes (e.g., environment variables, CI config, linter rules)
- Documentation updates that do not affect runtime behavior
---
@@ -241,3 +243,11 @@ This is faster than:
7. Ship again
---
## Related Skills
- `methodology/verification-before-completion` -- Ensures tests are actually run and passing before claiming work is done
- `methodology/testing-anti-patterns` -- Avoid common testing mistakes that undermine TDD effectiveness
- `testing/pytest` -- Python-specific testing patterns and best practices for TDD
- `testing/vitest` -- TypeScript/JavaScript-specific testing patterns and best practices for TDD
- `methodology/writing-plans` — Planning implementation tasks for TDD workflow
@@ -0,0 +1,150 @@
# TDD Decision Tree
Quick reference for deciding when and how to apply Test-Driven Development.
---
## Decision: Should I Use TDD Here?
```
Is this code...
├─ Business logic or data transformation?
│ └─ YES: Always TDD. No exceptions.
├─ An API endpoint (REST, GraphQL, RPC)?
│ └─ YES: Always TDD. Write request/response tests first.
├─ A bug fix?
│ └─ YES: Always TDD. Write a failing test that reproduces the bug first.
├─ A utility function or helper?
│ └─ YES: Always TDD. These are the easiest to TDD — pure input/output.
├─ A database query or repository method?
│ └─ YES: Always TDD. Test the query behavior, not the SQL syntax.
├─ A state machine or workflow?
│ └─ YES: Always TDD. Test each transition.
├─ UI layout or styling (CSS, Tailwind, visual positioning)?
│ └─ TDD optional. Visual output is hard to assert meaningfully.
│ Use snapshot tests or visual regression tools instead.
├─ Configuration or environment setup?
│ └─ TDD optional. Test that config loads correctly, but don't
│ TDD every config value. Integration tests are more useful.
├─ A database migration?
│ └─ TDD optional. Test that migration runs forward and backward.
│ Don't TDD the migration SQL itself.
├─ A prototype or spike?
│ └─ TDD optional. Spikes are throwaway. But if the spike becomes
│ real code, stop and add tests before continuing.
├─ Third-party integration glue code?
│ └─ TDD the contract, not the integration. Write tests against
│ the interface you expect, mock the external service.
└─ Generated code (scaffolding, boilerplate)?
└─ TDD optional. Test the generator if you wrote it.
Don't TDD the generated output.
```
---
## Decision Factors
When the tree above doesn't give a clear answer, weigh these factors:
| Factor | Favors TDD | Favors Test-After |
|--------|-----------|-------------------|
| **Testability** | Clear inputs/outputs, deterministic | Heavy side effects, UI rendering |
| **Complexity** | Multiple branches, edge cases | Straightforward single-path logic |
| **Risk** | Failure is costly (data loss, security) | Failure is cosmetic or low-impact |
| **Stability** | Requirements are clear and stable | Requirements are still changing |
| **Team convention** | Team expects TDD | Team doesn't practice TDD |
| **Confidence** | You're unsure how to implement it | You've built this exact thing before |
**Rule of thumb:** If you're unsure, use TDD. The cost of writing a test first is low. The cost of a bug in untested code is high.
---
## The TDD Cycle
```
1. RED — Write a failing test that defines the desired behavior
2. GREEN — Write the minimum code to make the test pass
3. REFACTOR — Clean up without changing behavior (tests still pass)
4. REPEAT — Next behavior
```
### Common Mistakes
- **Writing too much test at once** — Test one behavior per cycle
- **Writing implementation before the test fails** — The failing test is the spec
- **Skipping refactor** — Technical debt accumulates in GREEN if you don't clean up
- **Testing implementation details** — Test what it does, not how it does it
---
## Handling Legacy Code Without Tests
Legacy code (code without tests) requires a different entry point into TDD.
### Step 1: Characterization Tests
Before changing anything, write tests that capture current behavior:
```python
# Characterization test — documents what the code DOES, not what it SHOULD do
def test_calculate_total_current_behavior():
result = calculate_total(items=[{"price": 10, "qty": 2}])
assert result == 20 # Observed behavior, may or may not be correct
```
### Step 2: Identify the Change Boundary
What's the smallest piece of code you need to change? Draw a boundary around it.
### Step 3: Add Seams
If the code is untestable (hard dependencies, global state), add seams:
- Extract method
- Inject dependencies
- Wrap external calls
### Step 4: TDD the Change
Now that you have characterization tests protecting existing behavior and seams allowing isolation, use the normal RED-GREEN-REFACTOR cycle for your change.
### Step 5: Decide What to Keep
After the change, decide which characterization tests to keep:
- **Keep** tests that document important behavior
- **Replace** tests that covered the code you changed (your TDD tests are better)
- **Remove** tests that only existed to enable your refactoring
---
## TDD by Test Type
| Test Type | TDD Approach |
|-----------|-------------|
| **Unit tests** | Standard RED-GREEN-REFACTOR. One behavior per cycle. |
| **Integration tests** | Write the test against the integration boundary first. May need stubs for external services during RED phase. |
| **API tests** | Define the request and expected response first. Implement handler to make it pass. |
| **E2E tests** | Not typically TDD'd per-cycle. Write E2E tests for critical paths after unit/integration TDD. |
---
## Quick Checklist
Before claiming a task is done with TDD:
- [ ] Every production function has at least one test that was written before the function
- [ ] No test was written after the code it tests (except characterization tests for legacy code)
- [ ] All tests pass
- [ ] Code has been refactored after going GREEN
- [ ] Tests verify behavior, not implementation