I'm using pytest with pytest-xdist for parallel test running. It doesn't seem to honour the -s
option for passing through the standard output to the terminal as the tests are run. Is there any way to make this happen? I realise this could cause the output from the different processes to be jumbled up in the terminal but I'm ok with that.
Asked
Active
Viewed 4,514 times
21

Ralph Willgoss
- 11,750
- 4
- 64
- 67

Andrew Magee
- 6,506
- 4
- 35
- 58
-
There's an open issue for this here: https://github.com/pytest-dev/pytest/issues/680 – Chris Clark Sep 27 '15 at 21:12
-
3woohoo, pytest xdist now honors the `-s` option! See above issue. – Chris Clark Apr 05 '16 at 20:00
-
Also see https://github.com/pytest-dev/pytest/issues/5586 – Ralph Willgoss Apr 15 '21 at 16:05
3 Answers
15
I found a workaround, although not a full solution. By redirecting stdout to stderr, the output of print statements is displayed. This can be accomplished with a single line of Python code:
sys.stdout = sys.stderr
If placed in conftest.py, it applies to all tests.

Steve Saporta
- 4,581
- 3
- 30
- 32
-
This does not work. After doing this, `print` output still does not appear from tests executing within `xdist` workers. – ely Dec 09 '20 at 23:15
-
@ely are you using `log-cli-level=debug` and `-s` flags for pytest run? – SilentGuy Jul 15 '21 at 21:17
-
@steve-saporta Brilliant workaround. Works for me perfectly. Thanks. – SilentGuy Jul 15 '21 at 21:18
-
I was using `-s` but not `log-cli-level` - thanks for circling back to check! – ely Jul 16 '21 at 17:14
-
For me, this only works for prints. I have a simple test file (that has both a print and a `logging.warning`) alone in a dir and running with `pytest -s --log-cli-level=INFO -n 2 test_output.py`, I only see the print. Getting rid of `-n 2`, I see both. – Garrett Jul 12 '22 at 02:28
0
I used the followed code:
# conftest.py
import _pytest.capture
def get_capman(plugin_manager):
capman_list = filter(lambda p: isinstance(p, _pytest.capture.CaptureManager), plugin_manager._plugins)
return capman_list[0] if len(capman_list) == 1 else None
def get_xdist_slave(plugin_manager):
# TODO: have no idea how to check isinstance "__channelexec__.SlaveInteractor"
slave_list = filter(lambda p: hasattr(p, 'slaveid'), plugin_manager._plugins)
return slave_list[0] if len(slave_list) == 1 else None
def is_remote_xdist_session(plugin_manager):
return get_xdist_slave(plugin_manager) is not None
def pytest_configure(config):
if is_remote_xdist_session(config.pluginmanager) and get_capman(config.pluginmanager) is not None:
capman = get_capman(config.pluginmanager)
capman._method = "no"
capman.reset_capturings()
capman.init_capturings()
Insert it to conftest.py
The main thing is to be sure that it is remote session, and we have to reconfigure CaptureManager instance.
There one unresolved issue is how to check that remote object has "__channelexec__.SlaveInteractor
" type.

xSus
- 31
- 4
-
Hmm this doesn't seem to work for me. I have `print` statements in my fixtures which are definitely being executed but I don't see their output in the test run. – Andrew Magee Jan 17 '15 at 01:55
0
Steve's solution is great but sometimes we can't modifiy an conftest.py shared file.
I use -s
argument on pytest command :
pytest -s path/test_file.py
Inside my Python code I use these lines :
import sys
print("\nMy DEBUG line", file=sys.stderr)
pytest prompt me my DEBUG line. You can improve this solution according to your needs.

Samuel Dauzon
- 10,744
- 13
- 61
- 94