Pytest

Python testing made simple - fixtures, parametrize, plugins, and detailed assertion introspection

TL;DR

What: Python’s most popular testing framework.

Why: Simple syntax, powerful fixtures, plugins, parametrization, detailed reports.

Quick Start

Install:

pip install pytest

Create test (test_example.py):

def test_addition():
    assert 1 + 1 == 2

def test_string():
    assert "hello".upper() == "HELLO"

Run tests:

pytest                    # Run all tests
pytest test_example.py    # Run specific file
pytest -v                 # Verbose output

Cheatsheet

CommandDescription
pytestRun all tests
pytest -vVerbose mode
pytest -xStop on first failure
pytest -k "name"Run tests matching name
pytest --covCoverage report
pytest -n autoParallel execution

Gotchas

Fixtures

import pytest

@pytest.fixture
def sample_data():
    return {"name": "John", "age": 30}

def test_with_fixture(sample_data):
    assert sample_data["name"] == "John"

# Fixture with setup and teardown
@pytest.fixture
def database():
    db = connect_db()
    yield db
    db.close()

# Scoped fixtures
@pytest.fixture(scope="module")
def expensive_resource():
    return setup_resource()

Parametrization

import pytest

@pytest.mark.parametrize("input,expected", [
    (1, 2),
    (2, 4),
    (3, 6),
])
def test_double(input, expected):
    assert input * 2 == expected

@pytest.mark.parametrize("x,y,result", [
    (1, 1, 2),
    (2, 3, 5),
    (10, -5, 5),
])
def test_addition(x, y, result):
    assert x + y == result

Assertions

import pytest

def test_exceptions():
    with pytest.raises(ValueError):
        int("not a number")

    with pytest.raises(ZeroDivisionError):
        1 / 0

def test_approximate():
    assert 0.1 + 0.2 == pytest.approx(0.3)

def test_contains():
    assert "world" in "hello world"
    assert 5 in [1, 2, 3, 4, 5]

Markers

import pytest

@pytest.mark.slow
def test_slow_operation():
    # Runs only with: pytest -m slow
    pass

@pytest.mark.skip(reason="Not implemented yet")
def test_future_feature():
    pass

@pytest.mark.skipif(sys.version_info < (3, 10), reason="Requires Python 3.10+")
def test_new_feature():
    pass

@pytest.mark.xfail(reason="Known bug")
def test_known_issue():
    assert False

Mocking

from unittest.mock import Mock, patch

def test_mock():
    mock = Mock(return_value=42)
    assert mock() == 42

def test_patch():
    with patch('module.function') as mock_func:
        mock_func.return_value = "mocked"
        result = module.function()
        assert result == "mocked"

@patch('requests.get')
def test_api(mock_get):
    mock_get.return_value.json.return_value = {"id": 1}
    response = fetch_user(1)
    assert response["id"] == 1

Next Steps