Add capsysbinary fixture
`capsysbinary` works like `capsys` but produces bytes for `readouterr()`.
This commit is contained in:
parent
6161bcff6e
commit
219b758949
|
@ -180,7 +180,7 @@ class CaptureManager:
|
||||||
item.add_report_section(when, "stderr", err)
|
item.add_report_section(when, "stderr", err)
|
||||||
|
|
||||||
|
|
||||||
capture_fixtures = {'capfd', 'capfdbinary', 'capsys'}
|
capture_fixtures = {'capfd', 'capfdbinary', 'capsys', 'capsysbinary'}
|
||||||
|
|
||||||
|
|
||||||
def _ensure_only_one_capture_fixture(request, name):
|
def _ensure_only_one_capture_fixture(request, name):
|
||||||
|
@ -207,6 +207,22 @@ def capsys(request):
|
||||||
yield fixture
|
yield fixture
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def capsysbinary(request):
|
||||||
|
"""Enable capturing of writes to sys.stdout/sys.stderr and make
|
||||||
|
captured output available via ``capsys.readouterr()`` method calls
|
||||||
|
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
|
||||||
|
objects.
|
||||||
|
"""
|
||||||
|
_ensure_only_one_capture_fixture(request, 'capsysbinary')
|
||||||
|
# Currently, the implementation uses the python3 specific `.buffer`
|
||||||
|
# property of CaptureIO.
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
raise request.raiseerror('capsysbinary is only supported on python 3')
|
||||||
|
with _install_capture_fixture_on_item(request, SysCaptureBinary) as fixture:
|
||||||
|
yield fixture
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def capfd(request):
|
def capfd(request):
|
||||||
"""Enable capturing of writes to file descriptors 1 and 2 and make
|
"""Enable capturing of writes to file descriptors 1 and 2 and make
|
||||||
|
@ -506,10 +522,9 @@ class SysCapture:
|
||||||
setattr(sys, self.name, self.tmpfile)
|
setattr(sys, self.name, self.tmpfile)
|
||||||
|
|
||||||
def snap(self):
|
def snap(self):
|
||||||
f = self.tmpfile
|
res = self.tmpfile.getvalue()
|
||||||
res = f.getvalue()
|
self.tmpfile.seek(0)
|
||||||
f.truncate(0)
|
self.tmpfile.truncate()
|
||||||
f.seek(0)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
|
@ -528,6 +543,14 @@ class SysCapture:
|
||||||
self._old.flush()
|
self._old.flush()
|
||||||
|
|
||||||
|
|
||||||
|
class SysCaptureBinary(SysCapture):
|
||||||
|
def snap(self):
|
||||||
|
res = self.tmpfile.buffer.getvalue()
|
||||||
|
self.tmpfile.seek(0)
|
||||||
|
self.tmpfile.truncate()
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
class DontReadFromInput:
|
class DontReadFromInput:
|
||||||
"""Temporary stub class. Ideally when stdin is accessed, the
|
"""Temporary stub class. Ideally when stdin is accessed, the
|
||||||
capturing should be turned off, with possibly all data captured
|
capturing should be turned off, with possibly all data captured
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add ``capsysbinary`` a version of ``capsys`` which returns bytes from
|
||||||
|
``readouterr()``.
|
|
@ -85,9 +85,9 @@ of the failing function and hide the other one::
|
||||||
Accessing captured output from a test function
|
Accessing captured output from a test function
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
The ``capsys``, ``capfd``, and ``capfdbinary`` fixtures allow access to
|
The ``capsys``, ``capsysbinary``, ``capfd``, and ``capfdbinary`` fixtures
|
||||||
stdout/stderr output created during test execution. Here is an example test
|
allow access to stdout/stderr output created during test execution. Here is
|
||||||
function that performs some output related checks:
|
an example test function that performs some output related checks:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -115,11 +115,20 @@ same interface but allows to also capture output from
|
||||||
libraries or subprocesses that directly write to operating
|
libraries or subprocesses that directly write to operating
|
||||||
system level output streams (FD1 and FD2).
|
system level output streams (FD1 and FD2).
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
If the code under test writes non-textual data, you can capture this using
|
||||||
|
the ``capsysbinary`` fixture which instead returns ``bytes`` from
|
||||||
|
the ``readouterr`` method. The ``capfsysbinary`` fixture is currently only
|
||||||
|
available in python 3.
|
||||||
|
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
If the code under test writes non-textual data, you can capture this using
|
If the code under test writes non-textual data, you can capture this using
|
||||||
the ``capfdbinary`` fixture which instead returns ``bytes`` from
|
the ``capfdbinary`` fixture which instead returns ``bytes`` from
|
||||||
the ``readouterr`` method.
|
the ``readouterr`` method. The ``capfdbinary`` fixture operates on the
|
||||||
|
filedescriptor level.
|
||||||
|
|
||||||
|
|
||||||
.. versionadded:: 3.0
|
.. versionadded:: 3.0
|
||||||
|
|
|
@ -470,6 +470,38 @@ class TestCaptureFixture(object):
|
||||||
""")
|
""")
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
sys.version_info < (3,),
|
||||||
|
reason='only have capsysbinary in python 3',
|
||||||
|
)
|
||||||
|
def test_capsysbinary(self, testdir):
|
||||||
|
reprec = testdir.inline_runsource("""
|
||||||
|
def test_hello(capsysbinary):
|
||||||
|
import sys
|
||||||
|
# some likely un-decodable bytes
|
||||||
|
sys.stdout.buffer.write(b'\\xfe\\x98\\x20')
|
||||||
|
out, err = capsysbinary.readouterr()
|
||||||
|
assert out == b'\\xfe\\x98\\x20'
|
||||||
|
assert err == b''
|
||||||
|
""")
|
||||||
|
reprec.assertoutcome(passed=1)
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
sys.version_info >= (3,),
|
||||||
|
reason='only have capsysbinary in python 3',
|
||||||
|
)
|
||||||
|
def test_capsysbinary_forbidden_in_python2(self, testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
def test_hello(capsysbinary):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*test_hello*",
|
||||||
|
"*capsysbinary is only supported on python 3*",
|
||||||
|
"*1 error in*",
|
||||||
|
])
|
||||||
|
|
||||||
def test_partial_setup_failure(self, testdir):
|
def test_partial_setup_failure(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
def test_hello(capsys, missingarg):
|
def test_hello(capsys, missingarg):
|
||||||
|
@ -1233,7 +1265,7 @@ def test_dontreadfrominput_has_encoding(testdir):
|
||||||
reprec.assertoutcome(passed=1)
|
reprec.assertoutcome(passed=1)
|
||||||
|
|
||||||
|
|
||||||
def test_pickling_and_unpickling_enocded_file():
|
def test_pickling_and_unpickling_encoded_file():
|
||||||
# See https://bitbucket.org/pytest-dev/pytest/pull-request/194
|
# See https://bitbucket.org/pytest-dev/pytest/pull-request/194
|
||||||
# pickle.loads() raises infinite recursion if
|
# pickle.loads() raises infinite recursion if
|
||||||
# EncodedFile.__getattr__ is not implemented properly
|
# EncodedFile.__getattr__ is not implemented properly
|
||||||
|
|
Loading…
Reference in New Issue