How to Capture Logging Records with pytest caplog in Python

Capture and assert on logging records in pytest using the built-in caplog fixture.

Easy Python 3.9+ Aug 9, 2026 Testing & modern typing 15 views 0 copies

Requires third-party packages — install first
pip install pytest

Python code

28 lines
Python 3.9+
import logging
import pytest

def divide(a, b):
    """Divide two numbers and log an error if b is zero."""
    if b == 0:
        logging.error("Division by zero attempted")
        return None
    logging.info(f"Dividing {a} by {b}")
    return a / b

def test_divide_logs_error(caplog):
    with caplog.at_level(logging.ERROR):
        result = divide(10, 0)
    
    assert result is None
    assert "Division by zero attempted" in caplog.text
    
    # Check specific record details
    assert caplog.records[0].levelname == "ERROR"
    assert caplog.records[0].name == "root"

def test_divide_logs_info(caplog):
    with caplog.at_level(logging.INFO):
        result = divide(10, 2)
    
    assert result == 5.0
    assert "Dividing 10 by 2" in caplog.messages[0]

Output

stdout
2 passed in 0.01s

How it works

The caplog fixture automatically captures all logging messages emitted during a test. By using caplog.at_level(logging.ERROR), you temporarily set the root logger's level so that only ERROR-level messages (and above) are captured. The captured records are accessible via caplog.records, and you can check the entire log output as text with caplog.text. To get just the messages, use caplog.messages. This is a powerful way to verify that your code logs the right errors and informational messages without cluttering your test output.

Common mistakes

  • Forgetting to set the log level with caplog.at_level, which can cause messages to be missed
  • Using caplog.text when you only need message content and it includes timestamps and levels
  • Assuming caplog captures logs from child loggers without setting propagate=True

Variations

  1. Use caplog.set_level(logging.DEBUG) inside a test to capture DEBUG and above for the whole test.
  2. Use caplog.clear() between assertions to isolate log records from different sections.

Real-world use cases

  • Verifying that an authentication failure logs a security warning before returning an error to the user.
  • Checking that a data processing job logs every failed row for later debugging in production.
  • Ensuring a payment integration logs the exact reason for declined transactions for audit trails.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Testing & modern typing

Related tutorials and quizzes for this topic.