summaryrefslogtreecommitdiff
path: root/doc/en/capture.rst
blob: 900fe3fb4804ee24cca577f8c8040251197b031a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

.. _`captures`:

Capturing of the stdout/stderr output
=========================================================

Default stdout/stderr/stdin capturing behaviour
---------------------------------------------------------

During test execution any output sent to ``stdout`` and ``stderr`` is
captured.  If a test or a setup method fails its according captured
output will usually be shown along with the failure traceback. (this
behavior can be configured by the ``--show-capture`` command-line option).

In addition, ``stdin`` is set to a "null" object which will
fail on attempts to read from it because it is rarely desired
to wait for interactive input when running automated tests.

By default capturing is done by intercepting writes to low level
file descriptors.  This allows to capture output from simple
print statements as well as output from a subprocess started by
a test.

Setting capturing methods or disabling capturing
-------------------------------------------------

There are two ways in which ``pytest`` can perform capturing:

* file descriptor (FD) level capturing (default): All writes going to the
  operating system file descriptors 1 and 2 will be captured.

* ``sys`` level capturing: Only writes to Python files ``sys.stdout``
  and ``sys.stderr`` will be captured.  No capturing of writes to
  filedescriptors is performed.

.. _`disable capturing`:

You can influence output capturing mechanisms from the command line::

    pytest -s            # disable all capturing
    pytest --capture=sys # replace sys.stdout/stderr with in-mem files
    pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file

.. _printdebugging:

Using print statements for debugging
---------------------------------------------------

One primary benefit of the default capturing of stdout/stderr output
is that you can use print statements for debugging::

    # content of test_module.py

    def setup_function(function):
        print ("setting up %s" % function)

    def test_func1():
        assert True

    def test_func2():
        assert False

and running this module will show you precisely the output
of the failing function and hide the other one::

    $ pytest
    =========================== test session starts ============================
    platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
    rootdir: $REGENDOC_TMPDIR, inifile:
    collected 2 items

    test_module.py .F                                                    [100%]

    ================================= FAILURES =================================
    ________________________________ test_func2 ________________________________

        def test_func2():
    >       assert False
    E       assert False

    test_module.py:9: AssertionError
    -------------------------- Captured stdout setup ---------------------------
    setting up <function test_func2 at 0xdeadbeef>
    ==================== 1 failed, 1 passed in 0.12 seconds ====================

Accessing captured output from a test function
---------------------------------------------------

The ``capsys``, ``capsysbinary``, ``capfd``, and ``capfdbinary`` fixtures
allow access to stdout/stderr output created during test execution.  Here is
an example test function that performs some output related checks:

.. code-block:: python

    def test_myoutput(capsys): # or use "capfd" for fd-level
        print("hello")
        sys.stderr.write("world\n")
        captured = capsys.readouterr()
        assert captured.out == "hello\n"
        assert captured.err == "world\n"
        print("next")
        captured = capsys.readouterr()
        assert captured.out == "next\n"

The ``readouterr()`` call snapshots the output so far -
and capturing will be continued.  After the test
function finishes the original streams will
be restored.  Using ``capsys`` this way frees your
test from having to care about setting/resetting
output streams and also interacts well with pytest's
own per-test capturing.

If you want to capture on filedescriptor level you can use
the ``capfd`` fixture which offers the exact
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:: 3.3

The return value from ``readouterr`` changed to a ``namedtuple`` with two attributes, ``out`` and ``err``.

.. 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

If the code under test writes non-textual data, you can capture this using
the ``capfdbinary`` fixture which instead returns ``bytes`` from
the ``readouterr`` method.  The ``capfdbinary`` fixture operates on the
filedescriptor level.


.. versionadded:: 3.0

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