Implement new pytest_warning_captured hook

This commit is contained in:
Bruno Oliveira 2018-08-25 20:41:16 -03:00
parent 10f21b423a
commit ffd47ceefc
3 changed files with 69 additions and 31 deletions

View File

@ -535,6 +535,25 @@ def pytest_logwarning(message, code, nodeid, fslocation):
""" """
@hookspec(historic=True)
def pytest_warning_captured(warning, when, item):
"""
Process a warning captured by the internal pytest plugin.
:param warnings.WarningMessage warning:
The captured warning. This is the same object produced by :py:func:`warnings.catch_warnings`, and contains
the same attributes as :py:func:`warnings.showwarning`.
:param str when:
Indicates when the warning was captured. Possible values:
* ``"collect"``: during test collection.
* ``"runtest"``: during test execution.
:param pytest.Item|None item:
The item being executed if ``when == "runtest"``, else ``None``.
"""
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# doctest hooks # doctest hooks
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------

View File

@ -58,7 +58,7 @@ def pytest_configure(config):
@contextmanager @contextmanager
def catch_warnings_for_item(item): def deprecated_catch_warnings_for_item(item):
""" """
catches the warnings generated during setup/call/teardown execution catches the warnings generated during setup/call/teardown execution
of the given item and after it is done posts them as warnings to this of the given item and after it is done posts them as warnings to this
@ -80,40 +80,40 @@ def catch_warnings_for_item(item):
yield yield
for warning in log: for warning in log:
warn_msg = warning.message item.ihook.pytest_warning_captured.call_historic(
unicode_warning = False kwargs=dict(warning=warning, when="runtest", item=item)
if compat._PY2 and any(
isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args
):
new_args = []
for m in warn_msg.args:
new_args.append(
compat.ascii_escaped(m)
if isinstance(m, compat.UNICODE_TYPES)
else m
)
unicode_warning = list(warn_msg.args) != new_args
warn_msg.args = new_args
msg = warnings.formatwarning(
warn_msg,
warning.category,
warning.filename,
warning.lineno,
warning.line,
) )
item.warn("unused", msg) deprecated_emit_warning(item, warning)
if unicode_warning:
warnings.warn( def deprecated_emit_warning(item, warning):
"Warning is using unicode non convertible to ascii, " """
"converting to a safe representation:\n %s" % msg, Emits the deprecated ``pytest_logwarning`` for the given warning and item.
UnicodeWarning, """
) warn_msg = warning.message
unicode_warning = False
if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
new_args = []
for m in warn_msg.args:
new_args.append(
compat.ascii_escaped(m) if isinstance(m, compat.UNICODE_TYPES) else m
)
unicode_warning = list(warn_msg.args) != new_args
warn_msg.args = new_args
msg = warnings.formatwarning(
warn_msg, warning.category, warning.filename, warning.lineno, warning.line
)
item.warn("unused", msg)
if unicode_warning:
warnings.warn(
"Warning is using unicode non convertible to ascii, "
"converting to a safe representation:\n %s" % msg,
UnicodeWarning,
)
@pytest.hookimpl(hookwrapper=True) @pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item): def pytest_runtest_protocol(item):
with catch_warnings_for_item(item): with deprecated_catch_warnings_for_item(item):
yield yield

View File

@ -302,3 +302,22 @@ def test_filterwarnings_mark_registration(testdir):
) )
result = testdir.runpytest("--strict") result = testdir.runpytest("--strict")
assert result.ret == 0 assert result.ret == 0
@pytest.mark.filterwarnings("always")
def test_warning_captured_hook(testdir, pyfile_with_warnings):
collected = []
class WarningCollector:
def pytest_warning_captured(self, warning, when, item):
collected.append((warning.category, when, item.name))
result = testdir.runpytest(plugins=[WarningCollector()])
result.stdout.fnmatch_lines(["*1 passed*"])
expected = [
(UserWarning, "runtest", "test_func"),
(RuntimeWarning, "runtest", "test_func"),
]
assert collected == expected