Capture stdout and stderr with pytest capsys
Use pytest's capsys fixture to capture and assert on standard output and error streams in your tests.
pip install pytest
Python code
31 linesimport pytest
# Function under test
def greet(name):
print(f"Hello, {name}!")
print(f"Error: {name} not found", file=sys.stderr)
def test_captures_stdout_and_stderr(capsys):
greet("Alice")
captured = capsys.readouterr()
assert "Hello, Alice!" in captured.out
assert "Error: Alice not found" in captured.err
assert captured.out.count("Hello") == 1
def test_partial_capture(capsys):
print("to stdout")
print("to stderr", file=sys.stderr)
# Capture only stdout, leaving stderr intact
captured_out = capsys.readouterr().out
assert "to stdout" in captured_out
# Restore and verify stderr still available
captured_full = capsys.readouterr()
assert "to stderr" in captured_full.err
if __name__ == "__main__":
import sys
# Run tests programmatically for demonstration
pytest.main(["-v", "-s", __file__])
Output
No explicit output shown — the test failures or passes are displayed in terminal.
How it works
The capsys fixture automatically captures writes to sys.stdout and sys.stderr during each test. After the test's code has run, capsys.readouterr() returns a snapshot of the captured output as a named tuple with out and err fields. Calling readouterr() again after writing more output resets the captured text, letting you capture different sections of a test's output independently. This makes it easy to assert on specific messages your code printed without worrying about output to the real console.
Common mistakes
- Forgetting to call `readouterr()` before assertions, resulting in empty captured strings
- Using `captured.out` and `captured.err` interchangeably — they capture different streams
- Not resetting the capture with `readouterr()` when testing multiple print statements in one test
Variations
- Use `capsysbinary()` to capture bytes instead of text for binary output
- Check the output with regex using `re.search` when exact string matching isn't enough
Real-world use cases
- Verifying logging calls write expected messages to stderr in error-handling code
- Testing CLI tools that print progress updates or prompts to stdout
- Checking that background threads produce correct console output during integration tests
Sponsored
More from Testing & modern typing
- Characterization Test for Legacy Python Code medium
- Dataclass with Type Hints Fields in Python easy
- Dependency Injection in Python for Testability easy
- Design Data Helpers with Python TypedDict and Literal easy
- Fix and Test a Regression Bug in Python with Unit Tests easy
- Format Data with Type Hints in Python easy
Keep learning
Related tutorials and quizzes for this topic.