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

Introduce filter-warnings mark #2598

Merged
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
5 changes: 5 additions & 0 deletions _pytest/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def catch_warnings_for_item(item):
for arg in inifilters:
_setoption(warnings, arg)

mark = item.get_marker('filterwarnings')
if mark:
for arg in mark.args:
warnings._setoption(arg)

yield

for warning in log:
Expand Down
2 changes: 2 additions & 0 deletions changelog/2598.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Introduced ``@pytest.mark.filterwarnings`` mark which allows overwriting the warnings filter on a per test, class or module level.
See the `docs <https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings>`_ for more information.
34 changes: 34 additions & 0 deletions doc/en/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,40 @@ Both ``-W`` command-line option and ``filterwarnings`` ini option are based on P
`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
documentation for other examples and advanced usage.

``@pytest.mark.filterwarnings``
-------------------------------

.. versionadded:: 3.2

You can use the ``@pytest.mark.filterwarnings`` to add warning filters to specific test items,
allowing you to have finer control of which warnings should be captured at test, class or
even module level:

.. code-block:: python

import warnings

def api_v1():
warnings.warn(UserWarning("api v1, should use functions from v2"))
return 1

@pytest.mark.filterwarnings('ignore:api v1')
def test_one():
assert api_v1() == 1


Filters applied using a mark take precedence over filters passed on the command line or configured
by the ``filterwarnings`` ini option.

You may apply a filter to all tests of a class by using the ``filterwarnings`` mark as a class
decorator or to all tests in a module by setting the ``pytestmark`` variable:

.. code-block:: python

# turns all warnings into errors for this module
pytestmark = @pytest.mark.filterwarnings('error')


.. note::

``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
Expand Down
29 changes: 29 additions & 0 deletions testing/test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,32 @@ def test_my_warning(self):
result.stdout.fnmatch_lines([
'*== 1 passed in *',
])


@pytest.mark.parametrize('default_config', ['ini', 'cmdline'])
def test_filterwarnings_mark(testdir, default_config):
"""
Test ``filterwarnings`` mark works and takes precedence over command line and ini options.
"""
if default_config == 'ini':
testdir.makeini("""
[pytest]
filterwarnings = always
""")
testdir.makepyfile("""
import warnings
import pytest

@pytest.mark.filterwarnings('ignore::RuntimeWarning')
def test_ignore_runtime_warning():
warnings.warn(RuntimeWarning())

@pytest.mark.filterwarnings('error')
def test_warning_error():
warnings.warn(RuntimeWarning())

def test_show_warning():
warnings.warn(RuntimeWarning())
""")
result = testdir.runpytest('-W always' if default_config == 'cmdline' else '')
result.stdout.fnmatch_lines(['*= 1 failed, 2 passed, 1 warnings in *'])