Showing with 42 additions and 18 deletions.
  1. +2 −0 changelog/4013.feature.rst
  2. +13 −7 doc/en/warnings.rst
  3. +5 −7 src/_pytest/warnings.py
  4. +22 −4 testing/test_warnings.py
@@ -0,0 +1,2 @@
Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version
any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default.
@@ -101,22 +101,28 @@ DeprecationWarning and PendingDeprecationWarning
------------------------------------------------

.. versionadded:: 3.8
.. versionchanged:: 3.9

By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` if no other warning filters
are configured.
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning``.

To disable showing ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings, you might define any warnings
filter either in the command-line or in the ini file, or you can use:
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
(such as third-party libraries), in which case you might use the standard warning filters options (ini or marks).
For example:

.. code-block:: ini

[pytest]
filterwarnings =
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore:.*U.*mode is deprecated:DeprecationWarning


.. note::
If warnings are configured at the interpreter level, using
the `PYTHONWARNINGS <https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS>`_ environment variable or the
``-W`` command-line option, pytest will not configure any filters by default.

.. note::
This makes pytest more compliant with `PEP-0506 <https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners>`_ which suggests that those warnings should
This feature makes pytest more compliant with `PEP-0506 <https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners>`_ which suggests that those warnings should
be shown by default by test runners, but pytest doesn't follow ``PEP-0506`` completely because resetting all
warning filters like suggested in the PEP will break existing test suites that configure warning filters themselves
by calling ``warnings.simplefilter`` (see issue `#2430 <https://github.com/pytest-dev/pytest/issues/2430>`_
@@ -70,7 +70,11 @@ def catch_warnings_for_item(config, ihook, when, item):
cmdline_filters = config.getoption("pythonwarnings") or []
inifilters = config.getini("filterwarnings")
with warnings.catch_warnings(record=True) as log:
filters_configured = bool(cmdline_filters or inifilters or sys.warnoptions)

if not sys.warnoptions:
# if user is not explicitly configuring warning filters, show deprecation warnings by default (#2908)
warnings.filterwarnings("always", category=DeprecationWarning)
warnings.filterwarnings("always", category=PendingDeprecationWarning)

# filters should have this precedence: mark, cmdline options, ini
# filters should be applied in the inverse order of precedence
@@ -84,12 +88,6 @@ def catch_warnings_for_item(config, ihook, when, item):
for mark in item.iter_markers(name="filterwarnings"):
for arg in mark.args:
_setoption(warnings, arg)
filters_configured = True

if not filters_configured:
# if user is not explicitly configuring warning filters, show deprecation warnings by default (#2908)
warnings.filterwarnings("always", category=DeprecationWarning)
warnings.filterwarnings("always", category=PendingDeprecationWarning)

yield

@@ -495,8 +495,18 @@ def test_foo():
)
)

def test_shown_by_default(self, testdir):
@pytest.mark.parametrize("customize_filters", [True, False])
def test_shown_by_default(self, testdir, customize_filters):
"""Show deprecation warnings by default, even if user has customized the warnings filters (#4013)."""
self.create_file(testdir)
if customize_filters:
testdir.makeini(
"""
[pytest]
filterwarnings =
once::UserWarning
"""
)
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines(
[
@@ -512,7 +522,9 @@ def test_hidden_by_ini(self, testdir):
testdir.makeini(
"""
[pytest]
filterwarnings = once::UserWarning
filterwarnings =
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
"""
)
result = testdir.runpytest_subprocess()
@@ -523,7 +535,8 @@ def test_hidden_by_mark(self, testdir):
be displayed normally.
"""
self.create_file(
testdir, mark='@pytest.mark.filterwarnings("once::UserWarning")'
testdir,
mark='@pytest.mark.filterwarnings("ignore::PendingDeprecationWarning")',
)
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines(
@@ -536,7 +549,12 @@ def test_hidden_by_mark(self, testdir):

def test_hidden_by_cmdline(self, testdir):
self.create_file(testdir)
result = testdir.runpytest_subprocess("-W", "once::UserWarning")
result = testdir.runpytest_subprocess(
"-W",
"ignore::DeprecationWarning",
"-W",
"ignore::PendingDeprecationWarning",
)
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()

def test_hidden_by_system(self, testdir, monkeypatch):