Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access captures logs in teardown #3117

Merged
merged 2 commits into from
Jan 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Ahn Ki-Wook
Alexander Johnson
Alexei Kozlenok
Anatoly Bubenkoff
Anders Hovmöller
Andras Tim
Andreas Zeidler
Andrzej Ostrowski
Expand Down
12 changes: 12 additions & 0 deletions _pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ def __init__(self, item):
def handler(self):
return self._item.catch_log_handler

def get_handler(self, when):
"""
Get the handler for a specified state of the tests.
Valid values for the when parameter are: 'setup', 'call' and 'teardown'.
"""
return self._item.catch_log_handlers.get(when)

@property
def text(self):
"""Returns the log text."""
Expand Down Expand Up @@ -287,11 +294,16 @@ def _runtest_for(self, item, when):
"""Implements the internals of pytest_runtest_xxx() hook."""
with catching_logs(LogCaptureHandler(),
formatter=self.formatter) as log_handler:
if not hasattr(item, 'catch_log_handlers'):
item.catch_log_handlers = {}
item.catch_log_handlers[when] = log_handler
item.catch_log_handler = log_handler
try:
yield # run test
finally:
del item.catch_log_handler
if when == 'teardown':
del item.catch_log_handlers

if self.print_logs:
# Add a captured log section to the report.
Expand Down
1 change: 1 addition & 0 deletions changelog/3117.feature
Original file line number Diff line number Diff line change
@@ -0,0 +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.
9 changes: 9 additions & 0 deletions doc/en/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,12 @@ option names are:
* ``log_file_level``
* ``log_file_format``
* ``log_file_date_format``

Accessing logs from other test stages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The ``caplop.records`` fixture contains records from the current stage only. So
inside the setup phase it contains only setup logs, same with the call and
teardown phases. To access logs from other stages you can use
``caplog.get_handler('setup').records``. Valid stages are ``setup``, ``call``
and ``teardown``.
21 changes: 21 additions & 0 deletions testing/logging/test_fixture.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import logging

import pytest

logger = logging.getLogger(__name__)
sublogger = logging.getLogger(__name__ + '.baz')
Expand Down Expand Up @@ -68,3 +69,23 @@ def test_clear(caplog):
assert len(caplog.records)
caplog.clear()
assert not len(caplog.records)


@pytest.fixture
def logging_during_setup_and_teardown(caplog):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test looks good, thanks!

logger.info('a_setup_log')
yield
logger.info('a_teardown_log')
assert [x.message for x in caplog.get_handler('teardown').records] == ['a_teardown_log']


def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown):
assert not caplog.records
assert not caplog.get_handler('call').records
logger.info('a_call_log')
assert [x.message for x in caplog.get_handler('call').records] == ['a_call_log']

assert [x.message for x in caplog.get_handler('setup').records] == ['a_setup_log']

# This reachers into private API, don't use this type of thing in real tests!
assert set(caplog._item.catch_log_handlers.keys()) == {'setup', 'call'}