capture-stdout-stderr.rst

Overview

This document explains how **pytest** captures and manages **standard output (stdout)** and **standard error (stderr)** streams during test execution. It covers the default behavior of output capturing, the different capturing methods available, how to disable or configure capturing, and how to use pytest fixtures to access or manipulate captured output programmatically within tests.

The capturing mechanism is essential for producing clean test reports, enabling debugging via print statements, and supporting plugins that utilize output data. This file serves as a user guide and reference for understanding and controlling pytest's output capturing features.


Detailed Explanations

Default Capturing Behavior

By default, pytest captures all output sent to **stdout** and **stderr** during test execution. This includes output from print statements and subprocesses invoked by tests.


Capturing Methods

Pytest supports three capturing methods, selectable via the `--capture=` command-line option:

  1. fd (File Descriptor) capturing (default)
    Captures all writes to OS file descriptors 1 (stdout) and 2 (stderr). Suitable for capturing output from subprocesses or C extensions.

  2. sys capturing
    Captures only writes to Python-level sys.stdout and sys.stderr. Does not capture output written directly to file descriptors.

  3. tee-sys capturing (added in pytest 5.4)
    Captures Python-level writes to sys.stdout and sys.stderr and passes these writes through to the real output streams, enabling live printing alongside capturing (useful for plugins like junitxml).

**Disabling capturing** is possible with `pytest -s`, which turns off all capturing.

**Command-line examples:**

pytest -s                  # disables capturing
pytest --capture=sys       # uses sys capturing
pytest --capture=fd        # uses fd capturing (default)
pytest --capture=tee-sys   # tee sys capturing

Using Print Statements for Debugging

Because pytest captures output by default, developers can freely use print statements for debugging without cluttering test output.

Example:

def setup_function(function):
    print("setting up", function)

def test_func1():
    assert True

def test_func2():
    assert False

When running the above tests, only the output related to the failing test (`test_func2`) is shown, helping diagnose issues efficiently.


Accessing Captured Output Programmatically

Pytest provides several fixtures for capturing and interacting with **stdout** and **stderr** during tests:

**Usage example with `capsys`:**

def test_myoutput(capsys):
    print("hello")
    sys.stderr.write("world\n")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"

    print("next")
    captured = capsys.readouterr()
    assert captured.out == "next\n"

Temporarily Disabling Capture in a Test

You can disable capturing temporarily inside a test using the `disabled()` context manager available on capture fixtures:

def test_disabling_capturing(capsys):
    print("this output is captured")
    with capsys.disabled():
        print("output not captured, goes directly to sys.stdout")
    print("this output is also captured")

Within the `with` block, output is not captured and is sent directly to the console or terminal.


Implementation Details & Algorithms

The capturing system is designed to be transparent and restore original streams after tests, avoiding side effects on other parts of the application or test suite.


Interactions with Other System Parts


Usage Summary

Feature

Usage Example

Disable all capturing

`pytest -s`

Use sys capturing

`pytest --capture=sys`

Use fd capturing (default)

`pytest --capture=fd`

Use tee-sys capturing

`pytest --capture=tee-sys`

Access captured output in test

use `capsys` or `capfd` fixtures

Temporarily disable capture

`with capsys.disabled():`


Visual Diagram

The following flowchart illustrates the key capturing mechanisms and their relationships within this file's context:

flowchart TD
    A[Test Execution Starts] --> B{Capture Method?}
    B -->|fd (default)| C[Redirect OS File Descriptors (1,2)]
    B -->|sys| D[Replace sys.stdout and sys.stderr with in-memory streams]
    B -->|tee-sys| E[Wrap sys.stdout/stderr: Capture + Forward writes]
    B -->|disabled (-s)| F[No capturing; output goes directly to console]

    C --> G[Capture output from print + subprocesses]
    D --> H[Capture output from Python print statements only]
    E --> I[Capture + live display of Python prints]
    F --> J[Output directly shown on console]

    G --> K[Captured output available for reports and fixtures]
    H --> K
    I --> K
    J --> K

    K --> L[Fixtures: capsys, capfd, capsysbinary, capfdbinary]
    L --> M[Allow reading and manipulating captured output]
    M --> N[Disabled context manager to temporarily disable capture]

    style B fill:#f9f,stroke:#333,stroke-width:2px
    style L fill:#bbf,stroke:#333,stroke-width:2px

Summary

This file documents pytest's sophisticated and flexible stdout/stderr capturing system, enabling controlled output handling during tests. It balances capturing for clean reports and debugging convenience while supporting advanced use cases like subprocess output capture and live printing. The provided fixtures and command-line options allow users to tailor capturing to their testing needs efficiently.


End of Documentation for `capture-stdout-stderr.rst`