Red-Green-Refactor: Mastering Test-Driven Development in Python
Overview of Test-Driven Development
Prerequisites
To follow this guide, you should have a solid grasp of
Key Libraries & Tools
- unittest: The built-inPythonlibrary for creating and running tests. It provides a framework for organizing test cases and making assertions.
- PythonStandard Library: Used for basic data types like floats and integers, though decimals are often preferred for financial accuracy.
Code Walkthrough
The TDD cycle follows the Red-Green-Refactor pattern.
The Red Phase
First, we write a test for a method that doesn't exist yet. In our example, we want to compute an employee's payout. We create a test case that expects a specific float value.

import unittest
from employee import Employee
class TestEmployee(unittest.TestCase):
def setUp(self):
self.test_emp = Employee(name="Alice", pay_rate=100.0, hours_worked=10)
def test_payout_with_commission(self):
self.test_emp.contracts_landed = 10
# Expecting 1000 (base) + 1000 (commission) = 2000
self.assertAlmostEqual(self.test_emp.compute_payout(), 2000.0)
Running this now results in a failure (Red) because compute_payout is not implemented.
The Green Phase
Now, write the simplest possible code to make the test pass. Avoid over-engineering; just satisfy the assertion.
def compute_payout(self):
payout = self.pay_rate * self.hours_worked
if self.has_commission:
payout += self.commission_rate * self.contracts_landed
return payout
Running the tests again should yield a success (Green).
The Refactor Phase
With passing tests, you can safely clean up the code. You might split a generic employer_cost variable into specific categories like office_costs and 401k_costs. Because you have a test harness, you know immediately if your cleanup broke the logic.
Syntax Notes
- setUp: This method runs before every single test. Use it to create a fresh "test fixture" (like an Pythoninstance) so tests stay isolated.
- assertAlmostEqual: Essential when comparing floats. It accounts for the tiny rounding errors inherent in floating-point math.
Practical Examples
TDD is vital in financial systems where calculating tax or payroll requires extreme precision. It is also excellent for API development, where defining the input and output (the interface) first prevents scope creep.
Tips & Gotchas
- Isolate Tests: Never use global instances. If Test A modifies an object that Test B relies on, you'll face nightmare debugging scenarios.
- Don't Test Built-ins: You don't need to test if Pythoncan assign a variable. Focus on your custom logic.
- Use Fixed Values: Always compare your code's output against a hard-coded, known result rather than a copy of the logic inside the test file.

Fancy watching it?
Watch the full video and context