TDD Workflow: Step by Step
# Step 1: Write tests FIRST (no implementation yet)
Write comprehensive tests for calculateLoyaltyDiscount().
Function: calculateLoyaltyDiscount(tier: str, amount_cents: int) -> int
Returns: discount amount in cents
Rules:
- standard tier: 0% discount
- premium tier: 5% on orders over 5000 cents ($50), else 0%
- enterprise tier: 10% on all orders
- Invalid tier: raises ValueError
- Negative amount: raises ValueError
- Minimum discount: 0 (never negative)
Write tests covering all tiers, boundary conditions, and error cases.
DO NOT write the implementation. Tests only.
Run: bash("pytest tests/test_loyalty.py -v")
Expected: all FAIL (no implementation exists)
# Tests Claude generates:
def test_standard_tier_no_discount():
assert calculate_loyalty_discount("standard", 10000) == 0
def test_premium_below_threshold():
assert calculate_loyalty_discount("premium", 4999) == 0
def test_premium_above_threshold():
assert calculate_loyalty_discount("premium", 5000) == 250 # 5% of 5000
def test_enterprise_all_orders():
assert calculate_loyalty_discount("enterprise", 1000) == 100 # 10%
def test_invalid_tier():
with pytest.raises(ValueError, match="Invalid tier"):
calculate_loyalty_discount("gold", 1000)
def test_negative_amount():
with pytest.raises(ValueError):
calculate_loyalty_discount("premium", -100)
# Step 2: Verify tests fail (no implementation)
bash("pytest tests/test_loyalty.py -v")
# Expected: 6 FAILED — implementation doesn't exist
# Step 3: Implement to pass all tests
Write calculateLoyaltyDiscount() in src/loyalty.py
After writing: bash("pytest tests/test_loyalty.py -v")
# Expected: 6 PASSED
# Step 4: Full suite check
bash("pytest -v")
# Expected: all existing tests still pass (no regressions)
Using Existing Failing Tests as Spec
8 tests are failing in tests/test_payment_service.py after the refactor.
Read each test carefully. The tests define what PaymentService must do.
DO NOT modify any test file.
Fix PaymentService in src/services/payment_service.py to make all 8 pass.
After each significant change:
bash("pytest tests/test_payment_service.py -v")
Key Takeaways
- Tests first — unambiguous acceptance criteria before production code
- bash() to verify after each change — don’t accumulate uncertainty
- Never modify tests — fix the implementation
- Include error path tests — Claude needs to know failure behavior
- Full suite check after getting target tests green — verify no regressions