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
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
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
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.
toolbars
Modern SwiftUI toolbar patterns including customizable toolbars, search integration, transition effects, and platform-specific behavior. Use when implementing or customizing toolbars in SwiftUI.