Skip to content

Commit 3b3d237

Browse files
authored
Merge pull request #3117 from boxed/access_logs_in_teardown
Access captures logs in teardown
2 parents 1fd67c9 + c4c968f commit 3b3d237

File tree

5 files changed

+44
-0
lines changed

5 files changed

+44
-0
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Ahn Ki-Wook
99
Alexander Johnson
1010
Alexei Kozlenok
1111
Anatoly Bubenkoff
12+
Anders Hovmöller
1213
Andras Tim
1314
Andreas Zeidler
1415
Andrzej Ostrowski

_pytest/logging.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ def __init__(self, item):
128128
def handler(self):
129129
return self._item.catch_log_handler
130130

131+
def get_handler(self, when):
132+
"""
133+
Get the handler for a specified state of the tests.
134+
Valid values for the when parameter are: 'setup', 'call' and 'teardown'.
135+
"""
136+
return self._item.catch_log_handlers.get(when)
137+
131138
@property
132139
def text(self):
133140
"""Returns the log text."""
@@ -287,11 +294,16 @@ def _runtest_for(self, item, when):
287294
"""Implements the internals of pytest_runtest_xxx() hook."""
288295
with catching_logs(LogCaptureHandler(),
289296
formatter=self.formatter) as log_handler:
297+
if not hasattr(item, 'catch_log_handlers'):
298+
item.catch_log_handlers = {}
299+
item.catch_log_handlers[when] = log_handler
290300
item.catch_log_handler = log_handler
291301
try:
292302
yield # run test
293303
finally:
294304
del item.catch_log_handler
305+
if when == 'teardown':
306+
del item.catch_log_handlers
295307

296308
if self.print_logs:
297309
# Add a captured log section to the report.

changelog/3117.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
New ``caplog.get_handler(when)`` method which provides access to the underlying ``Handler`` class used to capture logging during each testing stage, allowing users to obtain the captured records during ``"setup"`` and ``"teardown"`` stages.

doc/en/logging.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,12 @@ option names are:
190190
* ``log_file_level``
191191
* ``log_file_format``
192192
* ``log_file_date_format``
193+
194+
Accessing logs from other test stages
195+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
196+
197+
The ``caplop.records`` fixture contains records from the current stage only. So
198+
inside the setup phase it contains only setup logs, same with the call and
199+
teardown phases. To access logs from other stages you can use
200+
``caplog.get_handler('setup').records``. Valid stages are ``setup``, ``call``
201+
and ``teardown``.

testing/logging/test_fixture.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
import logging
33

4+
import pytest
45

56
logger = logging.getLogger(__name__)
67
sublogger = logging.getLogger(__name__ + '.baz')
@@ -68,3 +69,23 @@ def test_clear(caplog):
6869
assert len(caplog.records)
6970
caplog.clear()
7071
assert not len(caplog.records)
72+
73+
74+
@pytest.fixture
75+
def logging_during_setup_and_teardown(caplog):
76+
logger.info('a_setup_log')
77+
yield
78+
logger.info('a_teardown_log')
79+
assert [x.message for x in caplog.get_handler('teardown').records] == ['a_teardown_log']
80+
81+
82+
def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown):
83+
assert not caplog.records
84+
assert not caplog.get_handler('call').records
85+
logger.info('a_call_log')
86+
assert [x.message for x in caplog.get_handler('call').records] == ['a_call_log']
87+
88+
assert [x.message for x in caplog.get_handler('setup').records] == ['a_setup_log']
89+
90+
# This reachers into private API, don't use this type of thing in real tests!
91+
assert set(caplog._item.catch_log_handlers.keys()) == {'setup', 'call'}

0 commit comments

Comments
 (0)