Test-Driven Development (TDD) Basics
TDD: Write tests FIRST, then write code to pass them. The cycle is Red (fail) → Green (pass) → Refactor (improve). This produces better-designed, well-tested code.
15 min•By Priygop Team•Updated 2026
TDD
TDD
# TDD Cycle: Red → Green → Refactor
# Step 1: RED — Write a failing test
def test_calculator_add():
calc = Calculator()
assert calc.add(2, 3) == 5
def test_calculator_subtract():
calc = Calculator()
assert calc.subtract(10, 4) == 6
def test_calculator_history():
calc = Calculator()
calc.add(2, 3)
calc.subtract(10, 4)
assert len(calc.history) == 2
# Step 2: GREEN — Write minimal code to pass
class Calculator:
def __init__(self):
self.history = []
def add(self, a, b):
result = a + b
self.history.append(f"{a} + {b} = {result}")
return result
def subtract(self, a, b):
result = a - b
self.history.append(f"{a} - {b} = {result}")
return result
# Step 3: REFACTOR — Improve without changing behavior
# (Already clean, but could extract _record method)
# Run TDD tests
print("=== TDD Demo ===")
tests = [test_calculator_add, test_calculator_subtract, test_calculator_history]
for test in tests:
try:
test()
print(f" ✅ {test.__name__}")
except Exception as e:
print(f" ❌ {test.__name__}: {e}")
# Show history
calc = Calculator()
calc.add(5, 3)
calc.subtract(10, 4)
calc.add(7, 8)
print(f"\nHistory:")
for entry in calc.history:
print(f" {entry}")Tip
Tip
Use logging instead of print for production debugging. Set up different log levels: DEBUG for dev, WARNING for production.
Diagram
Loading diagram…
pytest > unittest. Use fixtures for DRY. Mock external services. Run in CI with tox for multi-version.
Common Mistake
Warning
Leaving print() debugging statements in production code. Use logging and remove or disable debug output before deploying.
Quick Quiz
Practice Task
Note
(1) Set up logging with timestamps. (2) Log to both console and file. (3) Create a rotating log file handler.