Testing & Debugging pytest, unittest, Debugging with pdb

Python Testing & Debugging

Python Testing & Debugging

Write reliable code and squash bugs like a pro!

1. Testing with pytest

pytest is a popular, concise testing framework.

Installation

pip install pytest

Example Test

# test_math.py
def add(a, b):
    return a + b

def test_add():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

def test_add_edge_cases():
    with pytest.raises(TypeError):
        add("2", 3)  # Should raise TypeError

Run Tests:

pytest test_math.py -v  # -v for verbose output

Key Features:

  • Auto-discovers tests (files named test_*.py or *_test.py).
  • Fixtures for reusable setup/teardown.
  • Rich plugin ecosystem (e.g., pytest-cov for coverage).

2. Testing with unittest

unittest is Python’s built-in testing framework (inspired by JUnit).

Example Test

# test_strings.py
import unittest

class TestStringMethods(unittest.TestCase):
    def test_upper(self):
        self.assertEqual("hello".upper(), "HELLO")

    def test_split(self):
        s = "hello world"
        self.assertEqual(s.split(), ["hello", "world"])
        with self.assertRaises(TypeError):
            s.split(2)  # Invalid argument

if __name__ == "__main__":
    unittest.main()

Run Tests:

python -m unittest test_strings.py -v

Key Methods:

Method Purpose
assertEqual(a, b) Check if a == b
assertTrue(x) Check if x is True
assertRaises(Error) Check if code raises an error

3. Debugging with pdb

pdb (Python Debugger) helps you trace code execution and inspect variables.

Basic Commands

Command Action
n Execute next line
c Continue until next breakpoint
s Step into function
l List source code around current line
p <var> Print variable value
q Quit debugger

Example Workflow

# debug_example.py
def calculate_sum(numbers):
    total = 0
    for num in numbers:
        import pdb; pdb.set_trace()  # Set breakpoint
        total += num
    return total

print(calculate_sum([10, "20", 30]))  # Intentional bug

Debugging Session:

> debug_example.py(4)calculate_sum()
-> total += num
(Pdb) p num  # Print current num → "20"
(Pdb) p type(num)  # <class 'str'> → TypeError!
(Pdb) q  # Exit and fix the code

4. Real-World Scenarios

Scenario 1: Testing a Flask API

# test_app.py (using pytest)
from my_flask_app import app
import pytest

@pytest.fixture
def client():
    app.config["TESTING"] = True
    return app.test_client()

def test_home_page(client):
    response = client.get("/")
    assert response.status_code == 200
    assert b"Welcome" in response.data

def test_invalid_route(client):
    response = client.get("/invalid")
    assert response.status_code == 404

Scenario 2: Debugging a Data Pipeline

def process_data(data):
    result = []
    for item in data:
        # Debugging a data transformation issue
        import pdb; pdb.set_trace()
        processed = item * 2  # Example bug: item might be a string
        result.append(processed)
    return result

process_data([5, "10", 15])

5. Best Practices

Testing:

  • Follow AAA Pattern (Arrange, Act, Assert).
  • Write small, focused tests.
  • Use parameterized tests for multiple inputs:
@pytest.mark.parametrize("a,b,expected", [(2,3,5), (-1,1,0)])
def test_add(a, b, expected):
    assert add(a, b) == expected

Debugging:

  • Use conditional breakpoints:
if condition:
    import pdb; pdb.set_trace()
  • Debug tests with pytest --pdb (drop into debugger on failure).

Common Mistakes

  • ❌ Testing implementation, not behavior: Tests should focus on what the code does, not how.
  • ❌ Overusing print statements: Use pdb for systematic debugging.
  • ❌ Ignoring edge cases: Test empty inputs, invalid types, and boundary values.

Key Takeaways

  • ✅ pytest: Concise syntax, fixtures, and plugins.
  • ✅ unittest: Built-in, class-based structure.
  • ✅ pdb: Step through code, inspect variables, and fix bugs.

Practice Problem

Write a pytest test for a function that divides two numbers.

Add error handling to catch division by zero and test it.

Debug a failing test using pdb.

What’s Next?

  • Learn test coverage with pytest-cov or explore debugging in IDEs (VSCode, PyCharm)!

Post a Comment

Previous Post Next Post