diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index dac36b306..3e647d1a1 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -559,10 +559,13 @@ def pytest_warning_captured(warning_message, when, item): * ``"config"``: during pytest configuration/initialization stage. * ``"collect"``: during test collection. - * ``"runtest"``: during test execution. + * ``"setup"``: during test setup. + * ``"call"``: during test call. + * ``"teardown"``: during test teardown. :param pytest.Item|None item: - The item being executed if ``when == "runtest"``, else ``None``. + The item being executed if ``when`` is ``"setup"``, ``"call"`` or ``"teardown"``, otherwise + ``None``. """ diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 4ef4e7f0e..e0206883a 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -59,7 +59,7 @@ def pytest_configure(config): @contextmanager -def catch_warnings_for_item(config, ihook, item): +def catch_warnings_for_item(config, ihook, when, item): """ Context manager that catches warnings generated in the contained execution block. @@ -93,7 +93,7 @@ def catch_warnings_for_item(config, ihook, item): for warning_message in log: ihook.pytest_warning_captured.call_historic( - kwargs=dict(warning_message=warning_message, when="runtest", item=item) + kwargs=dict(warning_message=warning_message, when=when, item=item) ) @@ -130,22 +130,44 @@ def warning_record_to_str(warning_message): @pytest.hookimpl(hookwrapper=True, tryfirst=True) -def pytest_runtest_protocol(item): - with catch_warnings_for_item(config=item.config, ihook=item.ihook, item=item): +def pytest_runtest_setup(item): + with catch_warnings_for_item( + config=item.config, ihook=item.ihook, when="setup", item=item + ): + yield + + +@pytest.hookimpl(hookwrapper=True, tryfirst=True) +def pytest_runtest_call(item): + with catch_warnings_for_item( + config=item.config, ihook=item.ihook, when="call", item=item + ): + yield + + +@pytest.hookimpl(hookwrapper=True, tryfirst=True) +def pytest_runtest_teardown(item): + with catch_warnings_for_item( + config=item.config, ihook=item.ihook, when="teardown", item=item + ): yield @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_collection(session): config = session.config - with catch_warnings_for_item(config=config, ihook=config.hook, item=None): + with catch_warnings_for_item( + config=config, ihook=config.hook, when="collect", item=None + ): yield @pytest.hookimpl(hookwrapper=True) def pytest_terminal_summary(terminalreporter): config = terminalreporter.config - with catch_warnings_for_item(config=config, ihook=config.hook, item=None): + with catch_warnings_for_item( + config=config, ihook=config.hook, when="config", item=None + ): yield diff --git a/testing/test_warnings.py b/testing/test_warnings.py index eb4928a46..119b67cee 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -302,20 +302,48 @@ def test_filterwarnings_mark_registration(testdir): @pytest.mark.filterwarnings("always") -def test_warning_captured_hook(testdir, pyfile_with_warnings): +def test_warning_captured_hook(testdir): + testdir.makeconftest( + """ + from _pytest.warnings import _issue_config_warning + def pytest_configure(config): + _issue_config_warning(UserWarning("config warning"), config) + """ + ) + testdir.makepyfile( + """ + import pytest, warnings + + warnings.warn(UserWarning("collect warning")) + + @pytest.fixture + def fix(): + warnings.warn(UserWarning("setup warning")) + yield 1 + warnings.warn(UserWarning("teardown warning")) + + def test_func(fix): + warnings.warn(UserWarning("call warning")) + assert fix == 1 + """ + ) collected = [] class WarningCollector: def pytest_warning_captured(self, warning_message, when, item): - collected.append((warning_message.category, when, item.name)) + imge_name = item.name if item is not None else "" + collected.append((str(warning_message.message), when, imge_name)) result = testdir.runpytest(plugins=[WarningCollector()]) result.stdout.fnmatch_lines(["*1 passed*"]) expected = [ - (UserWarning, "runtest", "test_func"), - (RuntimeWarning, "runtest", "test_func"), + ("config warning", "config", ""), + ("collect warning", "collect", ""), + ("setup warning", "setup", "test_func"), + ("call warning", "call", "test_func"), + ("teardown warning", "teardown", "test_func"), ] assert collected == expected