Fix bugs using Test-Driven Development approach with regression prevention
Fix bugs using Test-Driven Development by first writing a failing test that reproduces the issue, then implementing the minimal fix. Use this when you need to prevent regressions and ensure bugs stay fixed with comprehensive test coverage.
/plugin marketplace add aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/plugin install tdd-workflow@aws-claude-code-plugins[bug-description-or-issue-number]You are a debugging expert who uses TDD principles. ALWAYS write a failing test that reproduces the bug before fixing it.
$ARGUMENTS
If no bug description was provided above, ask the user: "What bug would you like to fix using TDD? Please provide a description or issue number."
Before creating any tests, establish the project's test directory structure:
Scan for existing test structure:
tests/, test/, or src/tests/ directoriespyproject.toml, setup.py, or pytest.ini for test configurationCreate standard structure if needed:
tests/
├── unit/ # Unit tests for individual functions/classes
├── integration/ # Tests for component interactions
├── e2e/ # End-to-end system tests
├── fixtures/ # Test data and fixtures
└── conftest.py # Shared test configuration
Place bug fix tests appropriately:
tests/unit/test_[module_name].pytests/integration/test_[component_name].pytests/e2e/test_[feature_name].pydef test_reproduces_reported_bug():
"""
Bug Report: Users can login with expired tokens
This test MUST fail to confirm bug exists
"""
expired_token = create_token(expired=True)
# This should fail but currently passes (bug!)
with pytest.raises(AuthenticationError):
authenticate_with_token(expired_token)
# Confirm the bug exists - use proper test path
pytest tests/unit/test_auth_module.py::test_reproduces_reported_bug -v
# Expected: Test FAILS (confirming bug exists)
# FAILED tests/unit/test_auth_module.py::test_reproduces_reported_bug
def test_correct_token_expiry_behavior():
"""Define correct behavior through tests"""
# Valid token should work
valid_token = create_token(expired=False)
assert authenticate_with_token(valid_token) == True
# Expired token should fail
expired_token = create_token(expired=True)
with pytest.raises(AuthenticationError):
authenticate_with_token(expired_token)
# About-to-expire token should work
almost_expired = create_token(expires_in_seconds=60)
assert authenticate_with_token(almost_expired) == True
# Minimal fix to pass the test
def authenticate_with_token(token):
"""Fixed implementation"""
if token.is_expired(): # This check was missing!
raise AuthenticationError("Token expired")
return validate_token(token)
def test_prevents_token_expiry_regression():
"""Comprehensive tests to prevent regression"""
# Test various expiry scenarios
test_cases = [
(create_token(expired=True), False),
(create_token(expired=False), True),
(create_token(expires_at=yesterday), False),
(create_token(expires_at=tomorrow), True),
(create_token(expires_at=now), False),
]
for token, should_pass in test_cases:
if should_pass:
assert authenticate_with_token(token)
else:
with pytest.raises(AuthenticationError):
authenticate_with_token(token)
Before starting bug analysis, agents should:
Detect existing test infrastructure:
# Check for test directories
find . -type d -name "test*" -o -name "*test*" | head -10
# Look for test configuration files
ls -la pyproject.toml setup.py pytest.ini tox.ini
# Find existing test files to follow naming patterns
find . -name "test_*.py" -o -name "*_test.py" | head -5
Analyze current test organization:
Create missing test structure:
# Create standard Python test structure if missing
mkdir -p tests/{unit,integration,e2e,fixtures}
touch tests/conftest.py
Deploy concurrent debugging specialists: @code-archaeologist @business-analyst @test-generator @qa-engineer
def test_fixes_calculation_error():
"""Test for calculation bugs"""
# Bug: Total calculated incorrectly
cart = ShoppingCart()
cart.add_item(price=10, quantity=2)
cart.add_item(price=5, quantity=3)
# Should be 35, not 25 (bug!)
assert cart.total() == 35
def test_handles_empty_input():
"""Test for edge case bugs"""
# Bug: Crashes on empty list
result = process_items([])
assert result == [] # Should handle gracefully
def test_thread_safety():
"""Test for concurrency bugs"""
# Bug: Data corruption in parallel access
import threading
counter = Counter()
threads = []
for _ in range(100):
t = threading.Thread(target=counter.increment)
threads.append(t)
t.start()
for t in threads:
t.join()
assert counter.value == 100 # Should be exactly 100
def test_prevents_sql_injection():
"""Test for security bugs"""
# Bug: SQL injection possible
malicious_input = "'; DROP TABLE users; --"
# Should sanitize input
with pytest.raises(ValidationError):
execute_query(malicious_input)
Analyze Bug Report
Create Failing Test
Implement Fix
Verify Fix
Prevent Regression
# Fix authentication bug
/tdd-bugfix "Users can login with wrong password"
# Tests will be placed in: tests/unit/test_auth.py
# Fix data corruption bug
/tdd-bugfix "Database records deleted when updating user profile"
# Tests will be placed in: tests/integration/test_user_service.py
# Fix performance bug
/tdd-bugfix "API timeout when loading large datasets"
# Tests will be placed in: tests/e2e/test_api_performance.py
# Fix UI bug
/tdd-bugfix "Button click not working after form validation"
# Tests will be placed in: tests/e2e/test_form_interactions.py
Bug Analysis
Reproduction Test
Bug Fix
Verification
Regression Prevention
def test_array_bounds():
"""Prevent index errors"""
arr = [1, 2, 3]
# Bug: Accessing arr[3]
assert get_last_element(arr) == 3 # Not arr[len(arr)]
def test_handles_null_values():
"""Prevent NoneType errors"""
# Bug: Crashes on None
result = process_data(None)
assert result == default_value()
def test_type_conversion():
"""Prevent type errors"""
# Bug: String concatenation with number
result = format_message("Count", 42)
assert result == "Count: 42"
Before completing bug fix:
# GitHub Action for bug fixes with centralized test structure
name: TDD Bug Fix Validation
on:
pull_request:
types: [opened, synchronize]
jobs:
validate-bugfix:
if: contains(github.event.pull_request.labels.*.name, 'bugfix')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check for regression test in proper location
run: |
# Ensure bug fix includes test in tests/ directory
if ! git diff --name-only origin/main..HEAD | grep -q "tests/.*test_.*\.py"; then
echo "Bug fix must include test in tests/ directory"
exit 1
fi
- name: Run all tests with discovery
run: |
# Run tests from centralized location
pytest tests/ --tb=short --verbose
- name: Check coverage didn't decrease
run: |
# Coverage analysis on centralized test structure
pytest tests/ --cov=src --cov=. --cov-report=term
# Compare with main branch coverage