Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add disabled() method to capsys and capfd #1600

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
* New ``pytest_make_parametrize_id`` hook.
Thanks `@palaviv`_ for the PR.

* ``capsys`` and ``capfd`` now have a ``disabled()`` method, which is a context manager
that can be used to temporarily disable capture within a test.
Thanks `@nicoddemus`_ for the PR.

* New cli flag ``--fixtures-per-test`` that shows which fixtures are being used
for each selected test item. Features doc strings of fixtures by default.
Can also show where fixtures are defined if combined with ``-v``.
Expand Down
23 changes: 17 additions & 6 deletions _pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
from __future__ import with_statement

import contextlib
import sys
import os
from tempfile import TemporaryFile
Expand Down Expand Up @@ -146,8 +147,8 @@ def pytest_keyboard_interrupt(self, excinfo):
def pytest_internalerror(self, excinfo):
self.reset_capturings()

def suspendcapture_item(self, item, when):
out, err = self.suspendcapture()
def suspendcapture_item(self, item, when, in_=False):
out, err = self.suspendcapture(in_=in_)
item.add_report_section(when, "stdout", out)
item.add_report_section(when, "stderr", err)

Expand All @@ -162,7 +163,7 @@ def capsys(request):
"""
if "capfd" in request._funcargs:
raise request.raiseerror(error_capsysfderror)
request.node._capfuncarg = c = CaptureFixture(SysCapture)
request.node._capfuncarg = c = CaptureFixture(SysCapture, request)
return c

@pytest.fixture
Expand All @@ -175,17 +176,18 @@ def capfd(request):
request.raiseerror(error_capsysfderror)
if not hasattr(os, 'dup'):
pytest.skip("capfd funcarg needs os.dup")
request.node._capfuncarg = c = CaptureFixture(FDCapture)
request.node._capfuncarg = c = CaptureFixture(FDCapture, request)
return c


class CaptureFixture:
def __init__(self, captureclass):
def __init__(self, captureclass, request):
self.captureclass = captureclass
self.request = request

def _start(self):
self._capture = MultiCapture(out=True, err=True, in_=False,
Capture=self.captureclass)
Capture=self.captureclass)
self._capture.start_capturing()

def close(self):
Expand All @@ -200,6 +202,15 @@ def readouterr(self):
except AttributeError:
return self._outerr

@contextlib.contextmanager
def disabled(self):
capmanager = self.request.config.pluginmanager.getplugin('capturemanager')
capmanager.suspendcapture_item(self.request.node, "call", in_=True)
try:
yield
finally:
capmanager.resumecapture()


def safe_text_dupfile(f, mode, default_encoding="UTF8"):
""" return a open text file object that's a duplicate of f on the
Expand Down
15 changes: 15 additions & 0 deletions doc/en/capture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,19 @@ same interface but allows to also capture output from
libraries or subprocesses that directly write to operating
system level output streams (FD1 and FD2).


.. versionadded:: 2.10

To temporarily disable capture within a test, both ``capsys``
and ``capfd`` have a ``disabled()`` method that can be used
as a context manager, disabling capture inside the ``with`` block:

.. code-block:: python
def test_disabling_capturing(capsys):
print('this output is captured')
with capsys.disabled():
print('output not captured, going directly to sys.stdout')
print('this output is also captured')
.. include:: links.inc
16 changes: 16 additions & 0 deletions testing/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,22 @@ def test_log(capsys):
result = testdir.runpytest_subprocess(p)
assert 'closed' not in result.stderr.str()

@pytest.mark.parametrize('fixture', ['capsys', 'capfd'])
def test_disabled_capture_fixture(self, testdir, fixture):
testdir.makepyfile("""
def test_disabled({fixture}):
print('captured before')
with {fixture}.disabled():
print('while capture is disabled')
print('captured after')
""".format(fixture=fixture))
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines("""
*while capture is disabled*
""")
assert 'captured before' not in result.stdout.str()
assert 'captured after' not in result.stdout.str()


def test_setup_failure_does_not_kill_capturing(testdir):
sub1 = testdir.mkpydir("sub1")
Expand Down