Testing, Pytest & Debugging

๐Ÿ Python 3.12+ ๐ŸŸข Chapter 63 of 65 ๐Ÿ“‚ Phase 12: Automation and Professional Skills ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Unit vs Integration Testing ยท pytest Test Runner ยท Test Fixtures (@pytest.fixture) ยท Parametrization ยท Mocking Dependencies ยท Debugging with breakpoint()
Master automated software testing and debugging in Python: the difference between unit and integration tests, writing clean tests with pytest, leveraging reusable test fixtures, parameterized testing, mocking external network APIs, and interactive debugging with breakpoint().
1Unit Testing vs Integration Testing & The Pytest Framework

Automated software testing guarantees that code changes and refactoring do not introduce regression bugs.

Unit Tests vs Integration Tests:

  • Unit Tests: Test a single isolated function or class in memory with all external dependencies (databases, APIs) mocked out. They execute in milliseconds.
  • Integration Tests: Test how multiple components work together (e.g. testing whether a Flask route properly writes a record to a real PostgreSQL database).

Why Pytest is the Industry Standard:

Unlike Python's built-in unittest module which requires verbose classes and methods like self.assertEqual(a, b), pytest uses standard Python functions and plain assert statements with rich, detailed error diffs!

๐Ÿ’ป Blueprint: Pytest Fixtures, Assertions, and Parametrization
# Production Pytest Test Suite Architecture Blueprint:
"""
import pytest
from banking import BankAccount

# 1. Reusable Test Fixture:
@pytest.fixture
def active_account():
    # Setup: Create a fresh test account before each test
    account = BankAccount(owner="Balaji", initial_balance=5000.0)
    return account

# 2. Unit Test using standard assert statements:
def test_initial_balance(active_account):
    assert active_account.balance == 5000.0
    assert active_account.owner == "Balaji"

def test_deposit_funds(active_account):
    active_account.deposit(2000.0)
    assert active_account.balance == 7000.0

def test_withdraw_insufficient_funds_raises_error(active_account):
    with pytest.raises(ValueError, match="Insufficient funds"):
        active_account.withdraw(10000.0) # Attempting to overdraft!

# 3. Parameterized Testing: Run multiple test cases with one function!
@pytest.mark.parametrize("deposit_amount, expected_balance", [
    (500.0, 5500.0),
    (1500.0, 6500.0),
    (10000.0, 15000.0)
])
def test_multiple_deposits(active_account, deposit_amount, expected_balance):
    active_account.deposit(deposit_amount)
    assert active_account.balance == expected_balance
"""
print("Pytest Test Suite Blueprint Configured.")
๐Ÿ” Why @pytest.fixture is Powerful:

Fixtures ensure clean test isolation: each test function receives a freshly instantiated, pristine object, preventing state pollution between consecutive test runs.

2Interactive Debugging with Python's Built-in breakpoint() & pdb

Python 3.7+ introduced the built-in breakpoint() function. Calling breakpoint() anywhere in your code pauses execution and opens an interactive Python Debugger (PDB) shell right in your terminal!

PDB CommandShortAction / Meaning
nextnExecute the current line and advance to the next line.
stepsStep into the function call on the current line.
continuecResume normal program execution until the next breakpoint.
print(var)p varInspect the current runtime value of any variable.
quitqTerminate the debugging session and exit Python.
๐Ÿ’ป Example 2: Interactive Debugging Flow with breakpoint()
# Demonstrating Interactive Debugging Execution Flow:
def compute_discounted_cart(items, discount_pct):
    total = 0.0
    for item in items:
        price = item["price"]
        qty = item["qty"]
        # breakpoint()  <-- Un-commenting this pauses execution and drops into PDB shell!
        subtotal = price * qty
        total += subtotal
    
    final_amount = total * (1 - (discount_pct / 100))
    return final_amount

sample_cart = [
    {"name": "Python Book", "price": 899.0, "qty": 2},
    {"name": "USB Hub",     "price": 1299.0, "qty": 1}
]

total_charge = compute_discounted_cart(sample_cart, 10)
print(f"Final Discounted Cart Total: โ‚น{total_charge:,.2f}")
๐Ÿ” PDB vs Print Debugging:

With breakpoint(), you can dynamically modify variable values in memory, step through recursive calls line by line, and evaluate expressions without constantly restarting the script.

โš ๏ธ Common Developer Pitfall: Writing Tests that Rely on External Live APIs (Flaky Tests)

Unit tests that make live HTTP network calls will fail whenever the network is slow or third-party servers are down. Always use unittest.mock or pytest-mock to mock HTTP responses in unit tests.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Write a simple assertion test function test_email_validation() that tests whether an email validator returns True for "balaji@example.com" and False for "invalid_email".

Python 3 Practice Challenge โ–ถ Run in Compiler
def is_valid_email(email):
    return "@" in email and "." in email.split("@")[-1]

def run_tests():
    assert is_valid_email("balaji@example.com") == True, "Valid email failed!"
    assert is_valid_email("invalid_email") == False, "Invalid email passed!"
    assert is_valid_email("user@domain") == False, "Missing TLD passed!"
    print("โœ… All 3 Email Validation Tests Passed Successfully!")

run_tests()
Run This Challenge in Online Python IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q What is Code Coverage in testing?

Code Coverage (measured via pytest-cov) is the percentage of your application source code executed by your test suite, helping identify untested branches and edge cases.

Q What does unittest.mock.patch do?

patch() temporarily replaces a real function or network class (like requests.get) with a Mock object that returns pre-configured fake data during test execution.

Q What is TDD (Test-Driven Development)?

TDD is a software development process where you write a failing test first (Red), write the minimal code to make the test pass (Green), and then clean up the code (Refactor).

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on Python 3.12+ runtime ยท Last updated August 2026