Skip to content

Commit

Permalink
Add disabled() method to capsys and capfd
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus committed Jun 19, 2016
1 parent 308396a commit 72bf11c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
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

0 comments on commit 72bf11c

Please sign in to comment.