Description
If stdout or stderr objects are imported from sys, capsys
and capfd
cannot wrap them and thus nothing is captured. I would still expect to be able to capture them on capfd
but because pytest itself still manages to wrap them (prior to loading the test module I presume), nothing is actually written to these FDs.
import sys
from sys import stdout
def test_nothing_is_captured(capfd):
stdout.write('Hello\n')
stdout.flush()
cap = capfd.readouterr()
assert cap.out == 'Hello\n'
def test_capture_successful(capfd):
sys.stdout.write('Hello\n')
cap = capfd.readouterr()
assert cap.out == 'Hello\n'
Running this, the first one fails because nothing is captured. Adding os.system("echo Hello")
would make this test pass, as true-fd stdout output is still captured. The second test passes, presumably because capfd
then also wraps the sys.stdout object so that it can receive anything written there.
Pytest still prints on console the correct capture, showing that pytest itself successfully wrapped the stdout object:
tests/test_cap.py:8: AssertionError
------------------ Captured stdout call ------------------
Hello
================== short test summary info ==================
FAILED tests/test_cap.py::test_nothing_is_captured - AssertionError: assert '' == 'Hello\n'
================== 1 failed, 1 passed in 0.04s ==================
Running pytest 6.2.5 on Linux. Adding --capture=tee-sys
allows both tests to pass. This bug is somewhat related to #8900.
Since pytest itself has priority access to do its wrapping prior to loading any user code, it would be nice if capsys
and capfd
could also inject their code to the already provided wrapper, avoiding the error-prone rewrapping. This would allow both of them work as expected irregardless of how the application being tested imports the sys module.