← Back to Skills

TDD Bug Fix

general

Enforce TDD when fixing bugs - write a failing test first, then make it pass. Use when about to fix a bug, correct broken behavior, or resolve an issue in production code.

Test-Driven Bug Fixing

When fixing bugs, you MUST follow Kent Beck’s TDD discipline: write a failing test first, then make it pass. There is no world in which production code changes without a corresponding test change.

When to Activate

The Rule

NEVER edit production code to fix a bug without first touching tests.

The sequence is always:

  1. Reproduce - Write a failing test that demonstrates the bug
  2. Verify red - Confirm the test fails for the right reason
  3. Fix - Make the minimal change to pass the test
  4. Verify green - Confirm the test passes

Workflow

Step 1: Find Existing Tests

Before fixing anything, locate the test file:

spec/          # RSpec
test/          # Minitest, Jest, etc.
__tests__/     # Jest convention
*.test.ts      # Test file patterns
*.spec.rb

If no tests exist for the code being fixed, create them.

Step 2: Write a Failing Test

Write a test that:

# Example: Bug where API client uses wrong encoding
context 'when sending data to the API' do
  it 'sends JSON-encoded body, not form-encoded' do
    # This test will FAIL with current code (form encoding)
    # and PASS after the fix (JSON encoding)
    expect(request.content_type).to eq('application/json')
  end
end

Step 3: Verify the Test Fails

Run the test and confirm it fails. This proves:

Step 4: Fix the Production Code

Now, and only now, edit the production code to fix the bug.

Step 5: Verify the Test Passes

Run the test again. It should pass. This proves:

Exceptions

Do NOT require test changes for:

If there’s no spec/, test/, or __tests__/ directory, skip the TDD workflow.

Examples

Good: TDD Bug Fix

User: The API calls are failing

Agent: I see the issue - HTTParty is using form encoding instead of JSON.
       First, let me write a failing test to reproduce this bug.

       [Writes test in spec/lib/api_client_spec.rb]

       Running the test... it fails as expected - the request uses
       form encoding.

       Now let me fix the client to use JSON:

       [Edits lib/api_client.rb]

       Running the test again... it passes. The bug is fixed.

Bad: Skipping the Test

User: The API calls are failing

Agent: Same HTTParty issue as the rake task - form encoding isn't working
       correctly. Let me fix the client to use JSON:

       [Edits lib/api_client.rb WITHOUT touching tests]

       # THIS IS WRONG - no test was written to reproduce the bug

Self-Check

Before editing any production code to fix a bug, ask yourself:

  1. Have I identified the failing behavior?
  2. Have I written a test that reproduces it?
  3. Have I seen the test fail?

If the answer to any of these is “no”, STOP and write the test first.

Why This Matters

From Kent Beck’s “Test-Driven Development: By Example”:

“The goal is clean code that works. First we’ll make it work, then we’ll make it clean.”

But we can’t know it “works” without a test. A bug fix without a test is:

The test IS the proof that the bug is fixed.