The caplog fixture captures records emitted during a test and exposes logger name, level, message, and each LogRecord. This is more reliable than redirecting stdout when an application uses logging.

import logging

logger = logging.getLogger("app.pagamentos")

def cobrar(valor: int) -> None:
    if valor <= 0:
        logger.warning("valor inválido", extra={"valor": valor})

def test_registra_valor_invalido(caplog) -> None:
    caplog.set_level(logging.WARNING, logger="app.pagamentos")
    cobrar(0)

    assert ("app.pagamentos", logging.WARNING, "valor inválido") \
        in caplog.record_tuples

set_level() narrows capture to relevant events and can target one logger. record_tuples simplifies assertions on name, level, and message, while records exposes structured fields supplied through extra.

Practical guidance

Test event meaning rather than timestamps, colors, or full formatting. Avoid assertions on internal wording that is not a contract. If logging configuration replaces handlers and removes the capture handler, records may disappear; fix the test configuration instead of hiding the issue.

Review Python logging and organize dependencies with pytest fixtures.

The official pytest logging documentation, accessed July 22, 2026, documents the API and its constraints.