Test-Driven Development (TDD) Cheat Sheet
Covers the red-green-refactor loop, writing the smallest failing test first, test doubles, and common TDD anti-patterns to avoid.
2 PagesBeginnerFeb 2, 2026
The Red-Green-Refactor Loop
Write a failing test, make it pass with the simplest code, then clean up — repeat in small steps.
python
# 1. RED — write a failing test for behavior that doesn't exist yetdef test_calculates_total_with_tax(): cart = ShoppingCart() cart.add_item(price=100, tax_rate=0.08) assert cart.total() == 108# 2. GREEN — write the minimum code to passclass ShoppingCart: def __init__(self): self.items = [] def add_item(self, price, tax_rate): self.items.append((price, tax_rate)) def total(self): return sum(p * (1 + t) for p, t in self.items)# 3. REFACTOR — clean up implementation/tests with the safety net of a green test# (extract a Money value object, rename variables, etc.) — behavior stays the same
Test Doubles: Stub, Mock, Fake, Spy
Isolate the unit under test from slow/external dependencies.
python
from unittest.mock import Mockdef test_sends_confirmation_email_on_order(): email_service = Mock() # mock: verifies interaction order_service = OrderService(email_service=email_service) order_service.place_order(order_id=1, email="a@example.com") email_service.send.assert_called_once_with( to="a@example.com", template="order_confirmation" )class FakePaymentGateway: # fake: working lightweight implementation def __init__(self): self.charges = [] def charge(self, amount): self.charges.append(amount) return Truedef test_charges_payment_gateway(): gateway = FakePaymentGateway() service = CheckoutService(gateway) service.checkout(amount=50) assert gateway.charges == [50]
Parametrized Tests for Edge Cases
TDD works best when you drive out edge cases one small test at a time.
python
import pytest@pytest.mark.parametrize("price,tax_rate,expected", [ (100, 0.0, 100), # no tax (100, 0.08, 108), # standard case (0, 0.08, 0), # zero price (-10, 0.08, ValueError), # invalid: negative price should raise])def test_total_with_various_inputs(price, tax_rate, expected): cart = ShoppingCart() if expected is ValueError: with pytest.raises(ValueError): cart.add_item(price, tax_rate) else: cart.add_item(price, tax_rate) assert cart.total() == expected
TDD Principles & Anti-Patterns
What good TDD looks like, and the traps that erode it.
- Arrange-Act-Assert- structure every test in these three clear sections
- One assertion concept per test- keeps failures diagnostic and tests independent
- Test behavior, not implementation- anti-pattern: asserting on private internals couples tests to refactors
- Slow test suite- anti-pattern: hitting real DB/network in unit tests kills the fast feedback loop
- Fragile mocks- anti-pattern: over-mocking collaborators makes tests break on harmless refactors
- Triangulation- generalize an implementation only once a second test forces you to
- F.I.R.S.T.- Fast, Independent, Repeatable, Self-validating, Timely — the properties of a good test
Pro Tip
If you're stuck writing the 'right' implementation, write the most deliberately fake/hardcoded version that passes the test first (e.g. `return 108`) — it forces you to write the next failing test that breaks the fake, which naturally drives out the real logic.
Was this cheat sheet helpful?
Explore Topics
#TestDrivenDevelopmentTDD#TestDrivenDevelopmentTDDCheatSheet#Programming#Beginner#Red#Green#Refactor#Loop#Testing#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance