Codeskill

Learn to code, step by step

Pytest fundamentals

Pytest for testing Python you actually care about. Tests are not homework – they are the safety net when you refactor idiomatic code into packaged modules and Flask routes.

Install and first test

pip install pytest
# tests/test_helpers.py
from mytool.helpers import normalise_email

def test_normalise_email_strips_and_lowercases():
    assert normalise_email("  Alice@Example.com ") == "alice@example.com"
pytest -q

Arrange, act, assert

Structure tests in three beats: set up data, run the behaviour, check the outcome. No mystery about what failed.

def test_add_vat():
    # arrange
    net = 100.0
    # act
    gross = add_vat(net, rate=0.20)
    # assert
    assert gross == 120.0

pytest.raises for exceptions

import pytest

def test_balance_cannot_go_negative():
    account = Account(10)
    with pytest.raises(ValueError):
        account.balance = -1

Fixtures for shared setup

import pytest
from pathlib import Path

@pytest.fixture
def temp_db(tmp_path: Path):
    db_file = tmp_path / "test.db"
    connection = sqlite3.connect(db_file)
    connection.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
    yield connection
    connection.close()

tmp_path is a built-in fixture – a temporary directory pytest cleans up for you.

Parametrize repeated cases

@pytest.mark.parametrize(
    "raw,expected",
    [
        ("alice@example.com", "alice@example.com"),
        ("", ""),
        ("  BOB@EXAMPLE.COM", "bob@example.com"),
    ],
)
def test_normalise_email_cases(raw, expected):
    assert normalise_email(raw) == expected

Testing Flask apps

import pytest
from myapp import create_app

@pytest.fixture
def client():
    app = create_app({"TESTING": True})
    return app.test_client()

def test_index_returns_200(client):
    response = client.get("/")
    assert response.status_code == 200

What to test first

  • Pure functions with clear inputs and outputs.
  • Validation and error paths you are afraid to touch.
  • HTTP routes that must not regress after a refactor.

Next: CLI tools with argparse and Click – turning your packaged module into something you can run from the terminal.

PreviousScraping responsibly