Pytest
Coding
Debugging Techniques
Standard Output/Error
Python Programming

How to see normal stdout/stderr console print() output from code during a pytest run?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Pytest captures stdout and stderr by default so test output stays clean and focused on failures. That is useful most of the time, but when you are debugging a test or inspecting real-time output, you need to know how to disable capture or work with it deliberately.

The Quick Answer: Use -s

If you want print output to appear live in the terminal during the test run, disable capture entirely.

bash
pytest -s

This is equivalent to:

bash
pytest --capture=no

With capture disabled, normal print() calls and writes to sys.stderr show up immediately in the console.

Understanding Pytest Capture Modes

Pytest supports several capture modes, and choosing the right one matters:

  • '--capture=no or -s: no capture, output goes straight to the terminal'
  • '--capture=sys: captures Python-level writes to sys.stdout and sys.stderr'
  • '--capture=fd: captures file descriptor writes, including many subprocess outputs'
  • '--capture=tee-sys: shows Python output live while still capturing it for reports'

That last mode is especially useful when you want live visibility without giving up captured output in failure reports.

bash
pytest --capture=tee-sys

Captured Output Is Still Visible on Failure

Even with normal capture enabled, pytest often shows captured output when a test fails. That means you may not need -s for every debugging session.

python
def test_example():
    print("debug line before assertion")
    assert 2 + 2 == 5

If this test fails, pytest usually includes the captured output in the failure report.

Use capsys When You Want to Assert on Output

Sometimes you do not want live terminal output at all. You want to inspect what the code printed as part of the test itself. That is what the capsys fixture is for.

python
1def greet():
2    print("hello")
3
4
5def test_greet(capsys):
6    greet()
7    captured = capsys.readouterr()
8    assert captured.out == "hello\n"
9    assert captured.err == ""

This keeps the test deterministic while still letting you work with output explicitly.

Use capfd for Lower-Level Writes

If the code under test writes at the file descriptor level, or if a subprocess is involved, capsys may not be enough. Use capfd instead.

python
1import os
2
3
4def write_fd():
5    os.write(1, b"hello from fd\n")
6
7
8def test_fd_output(capfd):
9    write_fd()
10    captured = capfd.readouterr()
11    assert captured.out == "hello from fd\n"

This matters when native code, subprocesses, or lower-level writes are part of the test path.

Temporarily Disable Capture Inside One Test

You can also keep normal capture enabled and disable it only around a small block of code.

python
1def test_debug_block(capsys):
2    print("captured")
3
4    with capsys.disabled():
5        print("visible in terminal")
6
7    print("captured again")

This is useful when you want just a short interactive debugging window without changing the entire test command.

Logging Is Often Better Than print

If the goal is diagnostic visibility rather than quick local debugging, structured logging may be a better tool than raw print() statements. Pytest integrates with Python logging and can display captured logs in failure output more cleanly than unstructured console prints.

Still, print() remains useful for short-lived investigation and simple examples.

Common Pitfalls

The biggest pitfall is assuming pytest "hides" output permanently. In most cases it captures output, and that captured text is still available in failure reports or via fixtures.

Another issue is using capsys when the code writes at the file descriptor level. In that case, capfd is often the right fixture.

Developers also disable capture globally with -s and then forget that this can make large test runs noisy and harder to scan.

Finally, do not confuse output capture with logging configuration. print() output and logging output are related only in the sense that both can appear during test runs; they are controlled differently.

Summary

  • Use pytest -s or pytest --capture=no to see live stdout and stderr.
  • Use --capture=tee-sys when you want live Python output and captured reports.
  • Use capsys to assert on printed output in a test.
  • Use capfd when lower-level file descriptor output or subprocess output is involved.
  • Disable capture only where needed so normal test runs stay readable.

Course illustration
Course illustration

All Rights Reserved.