fix issue128 - show captured output when capsys/capfd are in use
This commit is contained in:
parent
971f96468c
commit
3f17784386
|
@ -1,3 +1,8 @@
|
||||||
|
Changes between 2.2.4 and 2.2.5.dev
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
- fix issue128: show captured output when capsys/capfd are used
|
||||||
|
|
||||||
Changes between 2.2.3 and 2.2.4
|
Changes between 2.2.3 and 2.2.4
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#
|
#
|
||||||
__version__ = '2.2.4'
|
__version__ = '2.2.5.dev1'
|
||||||
|
|
|
@ -121,20 +121,21 @@ class CaptureManager:
|
||||||
def activate_funcargs(self, pyfuncitem):
|
def activate_funcargs(self, pyfuncitem):
|
||||||
if not hasattr(pyfuncitem, 'funcargs'):
|
if not hasattr(pyfuncitem, 'funcargs'):
|
||||||
return
|
return
|
||||||
assert not hasattr(self, '_capturing_funcargs')
|
assert not hasattr(self, '_capturing_funcarg')
|
||||||
self._capturing_funcargs = capturing_funcargs = []
|
capargs = []
|
||||||
for name, capfuncarg in pyfuncitem.funcargs.items():
|
for name, capfuncarg in pyfuncitem.funcargs.items():
|
||||||
if name in ('capsys', 'capfd'):
|
if name in ('capsys', 'capfd'):
|
||||||
capturing_funcargs.append(capfuncarg)
|
capargs.append(capfuncarg)
|
||||||
capfuncarg._start()
|
if capargs:
|
||||||
|
self._capturing_funcarg = capargs[0]
|
||||||
|
self._capturing_funcarg._start()
|
||||||
|
|
||||||
def deactivate_funcargs(self):
|
def deactivate_funcargs(self):
|
||||||
capturing_funcargs = getattr(self, '_capturing_funcargs', None)
|
capturing_funcarg = getattr(self, '_capturing_funcarg', None)
|
||||||
if capturing_funcargs is not None:
|
if capturing_funcarg:
|
||||||
while capturing_funcargs:
|
outerr = capturing_funcarg._finalize()
|
||||||
capfuncarg = capturing_funcargs.pop()
|
del self._capturing_funcarg
|
||||||
capfuncarg._finalize()
|
return outerr
|
||||||
del self._capturing_funcargs
|
|
||||||
|
|
||||||
def pytest_make_collect_report(self, __multicall__, collector):
|
def pytest_make_collect_report(self, __multicall__, collector):
|
||||||
method = self._getmethod(collector.config, collector.fspath)
|
method = self._getmethod(collector.config, collector.fspath)
|
||||||
|
@ -169,9 +170,12 @@ class CaptureManager:
|
||||||
|
|
||||||
@pytest.mark.tryfirst
|
@pytest.mark.tryfirst
|
||||||
def pytest_runtest_makereport(self, __multicall__, item, call):
|
def pytest_runtest_makereport(self, __multicall__, item, call):
|
||||||
self.deactivate_funcargs()
|
funcarg_outerr = self.deactivate_funcargs()
|
||||||
rep = __multicall__.execute()
|
rep = __multicall__.execute()
|
||||||
outerr = self.suspendcapture(item)
|
outerr = self.suspendcapture(item)
|
||||||
|
if funcarg_outerr is not None:
|
||||||
|
outerr = (outerr[0] + funcarg_outerr[0],
|
||||||
|
outerr[1] + funcarg_outerr[1])
|
||||||
if not rep.passed:
|
if not rep.passed:
|
||||||
addouterr(rep, outerr)
|
addouterr(rep, outerr)
|
||||||
if not rep.passed or rep.when == "teardown":
|
if not rep.passed or rep.when == "teardown":
|
||||||
|
@ -179,11 +183,15 @@ class CaptureManager:
|
||||||
item.outerr = outerr
|
item.outerr = outerr
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
|
error_capsysfderror = "cannot use capsys and capfd at the same time"
|
||||||
|
|
||||||
def pytest_funcarg__capsys(request):
|
def pytest_funcarg__capsys(request):
|
||||||
"""enables capturing of writes to sys.stdout/sys.stderr and makes
|
"""enables capturing of writes to sys.stdout/sys.stderr and makes
|
||||||
captured output available via ``capsys.readouterr()`` method calls
|
captured output available via ``capsys.readouterr()`` method calls
|
||||||
which return a ``(out, err)`` tuple.
|
which return a ``(out, err)`` tuple.
|
||||||
"""
|
"""
|
||||||
|
if "capfd" in request._funcargs:
|
||||||
|
raise request.LookupError(error_capsysfderror)
|
||||||
return CaptureFuncarg(py.io.StdCapture)
|
return CaptureFuncarg(py.io.StdCapture)
|
||||||
|
|
||||||
def pytest_funcarg__capfd(request):
|
def pytest_funcarg__capfd(request):
|
||||||
|
@ -191,8 +199,10 @@ def pytest_funcarg__capfd(request):
|
||||||
captured output available via ``capsys.readouterr()`` method calls
|
captured output available via ``capsys.readouterr()`` method calls
|
||||||
which return a ``(out, err)`` tuple.
|
which return a ``(out, err)`` tuple.
|
||||||
"""
|
"""
|
||||||
|
if "capsys" in request._funcargs:
|
||||||
|
raise request.LookupError(error_capsysfderror)
|
||||||
if not hasattr(os, 'dup'):
|
if not hasattr(os, 'dup'):
|
||||||
py.test.skip("capfd funcarg needs os.dup")
|
pytest.skip("capfd funcarg needs os.dup")
|
||||||
return CaptureFuncarg(py.io.StdCaptureFD)
|
return CaptureFuncarg(py.io.StdCaptureFD)
|
||||||
|
|
||||||
class CaptureFuncarg:
|
class CaptureFuncarg:
|
||||||
|
@ -204,8 +214,9 @@ class CaptureFuncarg:
|
||||||
|
|
||||||
def _finalize(self):
|
def _finalize(self):
|
||||||
if hasattr(self, 'capture'):
|
if hasattr(self, 'capture'):
|
||||||
self.capture.reset()
|
outerr = self.capture.reset()
|
||||||
del self.capture
|
del self.capture
|
||||||
|
return outerr
|
||||||
|
|
||||||
def readouterr(self):
|
def readouterr(self):
|
||||||
return self.capture.readouterr()
|
return self.capture.readouterr()
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -24,7 +24,7 @@ def main():
|
||||||
name='pytest',
|
name='pytest',
|
||||||
description='py.test: simple powerful testing with Python',
|
description='py.test: simple powerful testing with Python',
|
||||||
long_description = long_description,
|
long_description = long_description,
|
||||||
version='2.2.4',
|
version='2.2.5.dev1',
|
||||||
url='http://pytest.org',
|
url='http://pytest.org',
|
||||||
license='MIT license',
|
license='MIT license',
|
||||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||||
|
|
|
@ -373,6 +373,33 @@ class TestCaptureFuncarg:
|
||||||
""")
|
""")
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
|
||||||
|
def test_capsyscapfd(self, testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
def test_one(capsys, capfd):
|
||||||
|
pass
|
||||||
|
def test_two(capfd, capsys):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*ERROR*setup*test_one*",
|
||||||
|
"*capsys*capfd*same*time*",
|
||||||
|
"*ERROR*setup*test_two*",
|
||||||
|
"*capsys*capfd*same*time*",
|
||||||
|
"*2 error*"])
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("method", ["sys", "fd"])
|
||||||
|
def test_capture_is_represented_on_failure_issue128(self, testdir, method):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
def test_hello(cap%s):
|
||||||
|
print ("xxx42xxx")
|
||||||
|
assert 0
|
||||||
|
""" % method)
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"xxx42xxx",
|
||||||
|
])
|
||||||
|
|
||||||
@needsosdup
|
@needsosdup
|
||||||
def test_stdfd_functional(self, testdir):
|
def test_stdfd_functional(self, testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
|
|
Loading…
Reference in New Issue