tdd-bug-fix
Fix bugs using red-green-refactor — reproduce the bug as a failing test first, then fix it. Use when fixing bugs to ensure they never regress.
Best use case
tdd-bug-fix is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Fix bugs using red-green-refactor — reproduce the bug as a failing test first, then fix it. Use when fixing bugs to ensure they never regress.
Teams using tdd-bug-fix should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/tdd-bug-fix/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How tdd-bug-fix Compares
| Feature / Agent | tdd-bug-fix | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Fix bugs using red-green-refactor — reproduce the bug as a failing test first, then fix it. Use when fixing bugs to ensure they never regress.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# TDD Bug Fix
Fix bugs the right way: reproduce first, fix second, verify always. Especially critical when using AI to generate fixes — the test ensures the AI actually solved the problem.
## When This Skill Activates
Use this skill when the user:
- Reports a bug and wants it fixed
- Says "this is broken" or "this doesn't work"
- Asks to "fix and add a test" or "fix with TDD"
- Wants to ensure a bug doesn't come back
- Is skeptical of AI-generated fixes ("how do I know it's actually fixed?")
## Why TDD for Bug Fixes
```
Without TDD: With TDD:
Bug reported Bug reported
→ AI generates fix → Write failing test (RED)
→ Deploy → AI generates fix (GREEN)
→ Hope it works → Test passes — confirmed fixed
→ Bug returns later → Test prevents regression forever
```
## Process
### Phase 1: Understand the Bug
Gather information:
1. **What's the expected behavior?**
2. **What's the actual behavior?**
3. **Steps to reproduce?**
4. **Which code is involved?**
```
Grep: "[relevant keyword]" to find the source
Read: the suspected file(s)
```
Identify:
- [ ] The function/method where the bug lives
- [ ] The input that triggers the bug
- [ ] The incorrect output/behavior
- [ ] The correct expected output/behavior
### Phase 2: RED — Write the Failing Test
Write a test that **fails because of the bug**. This proves the bug exists.
#### Template: Logic Bug
```swift
import Testing
@testable import YourApp
@Suite("Bug Fix: [Brief description]")
struct BugFix_DescriptionTests {
@Test("should [expected behavior] — was [actual behavior]")
func reproduceBug() {
// Arrange — set up the conditions that trigger the bug
let calculator = PriceCalculator()
// Act — perform the operation that's broken
let result = calculator.applyDiscount(price: 100, percent: 50)
// Assert — what it SHOULD return (this will FAIL now)
#expect(result == 50.0) // Currently returns 0.5 (bug: divides by 100 twice)
}
}
```
#### Template: Async Bug
```swift
@Test("should return cached items when network fails — was crashing")
func reproduceBug() async throws {
let mockNetwork = MockNetworkClient(shouldFail: true)
let mockCache = MockCache(items: [.sample])
let service = DataService(network: mockNetwork, cache: mockCache)
// This should return cached data, but currently crashes
let items = try await service.fetchItems()
#expect(items.count == 1)
}
```
#### Template: State Bug
```swift
@Test("should update count after deletion — was showing stale count")
func reproduceBug() {
let manager = ItemManager()
manager.addItem(Item(title: "Test"))
manager.deleteItem(at: 0)
#expect(manager.count == 0) // Currently still returns 1
#expect(manager.items.isEmpty) // Currently still contains item
}
```
#### Template: Edge Case Bug
```swift
@Test("should handle empty input — was crashing with index out of range")
func reproduceBug() {
let parser = CSVParser()
// This crashes with empty string
let result = parser.parse("")
#expect(result.rows.isEmpty)
#expect(result.columns.isEmpty)
}
```
#### Template: UI State Bug
```swift
@Test("should show error state when API fails — was showing infinite spinner")
func reproduceBug() async {
let failingAPI = MockAPI(shouldFail: true)
let viewModel = ListViewModel(api: failingAPI)
await viewModel.loadData()
#expect(viewModel.state == .error) // Currently stuck on .loading
#expect(viewModel.isLoading == false)
}
```
**Run the test — it MUST fail.** If it passes, you haven't reproduced the bug.
```bash
xcodebuild test -scheme YourApp \
-only-testing "YourAppTests/BugFix_DescriptionTests"
```
### Phase 3: GREEN — Fix the Bug
Now fix the code to make the test pass. The fix should be **minimal** — only change what's needed.
#### Fix Guidelines
- **Change as little code as possible** to make the test pass
- **Don't refactor while fixing** — that's the next step
- **Don't fix other issues** you notice — file them separately
- **AI should target the specific test** — give Claude the failing test as context
```
Prompt to Claude: "Here's a failing test that reproduces a bug.
Fix the source code to make this test pass without breaking
any existing tests."
```
**Run the test — it MUST pass now.**
```bash
# Run the bug fix test
xcodebuild test -scheme YourApp \
-only-testing "YourAppTests/BugFix_DescriptionTests"
# Run ALL tests to check for regressions
xcodebuild test -scheme YourApp
```
### Phase 4: REFACTOR (Optional)
If the fix introduced duplication or the code could be cleaner:
1. **Refactor only with all tests passing**
2. **Run tests after each change**
3. **Keep the bug fix test** — it's now a permanent regression test
### Phase 5: Verify Completeness
Checklist before marking the bug as fixed:
- [ ] Failing test written that reproduces the bug
- [ ] Fix implemented — test now passes
- [ ] All existing tests still pass (no regressions)
- [ ] Edge cases covered (empty, nil, boundary values)
- [ ] Test is clearly named and documents the bug
- [ ] Fix is minimal — no unrelated changes
## Multiple Related Bugs
If a bug has multiple symptoms, write multiple tests:
```swift
@Suite("Bug Fix: Discount calculation errors")
struct BugFix_DiscountCalculationTests {
@Test("50% discount on $100 should be $50")
func fiftyPercentDiscount() {
let calc = PriceCalculator()
#expect(calc.applyDiscount(price: 100, percent: 50) == 50.0)
}
@Test("0% discount should return original price")
func zeroDiscount() {
let calc = PriceCalculator()
#expect(calc.applyDiscount(price: 100, percent: 0) == 100.0)
}
@Test("100% discount should return 0")
func fullDiscount() {
let calc = PriceCalculator()
#expect(calc.applyDiscount(price: 100, percent: 100) == 0.0)
}
@Test("discount on $0 should return $0")
func zeroPrice() {
let calc = PriceCalculator()
#expect(calc.applyDiscount(price: 0, percent: 50) == 0.0)
}
}
```
## Output Format
```markdown
## Bug Fix: [Description]
### Bug Summary
- **Expected**: [What should happen]
- **Actual**: [What was happening]
- **Root cause**: [Why it was broken]
### Test (RED)
```swift
// Failing test that reproduces the bug
```
### Fix (GREEN)
**File**: `path/to/file.swift:XX`
```swift
// Before (buggy)
// After (fixed)
```
### Verification
- [x] Bug test fails before fix
- [x] Bug test passes after fix
- [x] All existing tests still pass
- [x] Edge cases covered: [list]
### Regression Prevention
Test added: `Tests/BugFixes/BugFix_DescriptionTests.swift`
This test will catch any future regression of this bug.
```
## Common Pitfalls
| Pitfall | Problem | Solution |
|---------|---------|----------|
| Test passes before fix | You didn't reproduce the bug | Make assertions more specific |
| Fix breaks other tests | Fix was too broad | Revert and use smaller, targeted change |
| Test is too specific | Brittle, breaks on unrelated changes | Test behavior, not implementation details |
| Skipping the red step | No proof the test catches the bug | Always verify test fails first |
| Fixing multiple bugs at once | Can't isolate regressions | One bug = one test + one fix |
## References
- `testing/tdd-feature/` — for new features (not bug fixes)
- `testing/characterization-test-generator/` — for capturing existing behavior first
- `generators/test-generator/` — for general test generationRelated Skills
swiftui-ui-patterns
Best practices and example-driven guidance for building SwiftUI views and components. Use when creating or refactoring SwiftUI UI, designing tab architecture with TabView, composing screens, or needing component-specific patterns and examples.
watchOS
watchOS development guidance including SwiftUI for Watch, Watch Connectivity, complications, and watch-specific UI patterns. Use for watchOS code review, best practices, or Watch app development.
visionos-widgets
visionOS widget patterns including mounting styles, glass/paper textures, proximity-aware layouts, and spatial widget families. Use when creating or adapting widgets for visionOS.
test-data-factory
Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
test-contract
Generate protocol/interface test suites that any implementation must pass. Define the contract once, test every implementation. Use when designing protocols or swapping implementations.
tdd-refactor-guard
Pre-refactor safety checklist. Verifies test coverage exists before AI modifies existing code. Use before asking AI to refactor anything.
tdd-feature
Red-green-refactor scaffold for building new features with TDD. Write failing tests first, then implement to pass. Use when building new features test-first.
snapshot-test-setup
Set up SwiftUI visual regression testing with swift-snapshot-testing. Generates snapshot test boilerplate and CI configuration. Use for UI regression prevention.
integration-test-scaffold
Generate cross-module test harness with mock servers, in-memory stores, and test configuration. Use when testing networking + persistence + business logic together.
characterization-test-generator
Generates tests that capture current behavior of existing code before refactoring. Use when you need a safety net before AI-assisted refactoring or modifying legacy code.
testing
TDD and testing skills for iOS/macOS apps. Covers characterization tests, TDD workflows, test contracts, snapshot tests, and test infrastructure. Use for test-driven development, adding tests to existing code, or building test infrastructure.
webkit-integration
WebKit integration in SwiftUI using WebView and WebPage for embedding web content, navigation, JavaScript interop, and customization. Use when embedding web content in SwiftUI apps.