diff --git a/_pytest/warnings.py b/_pytest/warnings.py index b27c20b9d..1458c25c3 100644 --- a/_pytest/warnings.py +++ b/_pytest/warnings.py @@ -1,4 +1,6 @@ import os +from contextlib import contextmanager + import pytest import warnings @@ -38,8 +40,13 @@ def pytest_addoption(parser): "to warnings.filterwarnings. Process after -W and --pythonwarnings.") -@pytest.hookimpl(hookwrapper=True) -def pytest_runtest_call(item): +@contextmanager +def catch_warnings_for_item(item): + """ + catches the warnings generated during setup/call/teardown execution + of the given item and after it is done posts them as warnings to this + item. + """ args = item.config.getoption('pythonwarnings') or [] inifilters = item.config.getini("filterwarnings") with warnings.catch_warnings(record=True) as log: @@ -56,4 +63,23 @@ def pytest_runtest_call(item): msg = warnings.formatwarning( warning.message, warning.category, warning.filename, warning.lineno, warning.line) - item.config.warn("W0", msg, fslocation=None) + item.config.warn("unused", msg, fslocation=None) + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_call(item): + with catch_warnings_for_item(item): + yield + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_setup(item): + with catch_warnings_for_item(item): + yield + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_teardown(item): + with catch_warnings_for_item(item): + yield + diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 943c8244c..77eefb7e3 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -27,6 +27,34 @@ def test_normal_flow(testdir, pyfile_with_warnings): ]) +def test_setup_teardown_warnings(testdir, pyfile_with_warnings): + testdir.makepyfile(''' + import warnings + import pytest + + @pytest.fixture + def fix(): + warnings.warn(UserWarning("warning during setup")) + yield + warnings.warn(UserWarning("warning during teardown")) + + def test_func(fix): + pass + ''') + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + '*== %s ==*' % WARNINGS_SUMMARY_HEADER, + + '*test_setup_teardown_warnings.py:6: UserWarning: warning during setup', + ' warnings.warn(UserWarning("warning during setup"))', + + '*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown', + ' warnings.warn(UserWarning("warning during teardown"))', + '* 1 passed, 2 warnings*', + ]) + + + @pytest.mark.parametrize('method', ['cmdline', 'ini']) def test_as_errors(testdir, pyfile_with_warnings, method): args = ('-W', 'error') if method == 'cmdline' else ()