Skip to content

Commit a9a016a

Browse files
committed
Update documentation on how pytest.warns affects DeprecationWarning
Co-authored-by: Dani Sancas <[email protected]> On-behalf-of: @clarityai-eng <[email protected]> Signed-off-by: Tatiana Ovary <[email protected]>
1 parent 70cac3d commit a9a016a

File tree

3 files changed

+44
-18
lines changed

3 files changed

+44
-18
lines changed

changelog/9291.doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update documentation on how :func:`pytest.warns` affects :class:`DeprecationWarning`.

doc/en/how-to/capture-warnings.rst

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Running pytest now produces this output:
4242
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
4343
======================= 1 passed, 1 warning in 0.12s =======================
4444
45+
.. _`controlling-warnings`:
46+
4547
Controlling warnings
4648
--------------------
4749

@@ -176,11 +178,14 @@ using an external system.
176178
DeprecationWarning and PendingDeprecationWarning
177179
------------------------------------------------
178180

179-
180181
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
181182
user code and third-party libraries, as recommended by :pep:`565`.
182183
This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.
183184

185+
However, in the specific case where users capture any type of warnings in their test, either with
186+
:func:`pytest.warns`, :func:`pytest.deprecated_call` or using the :ref:`recwarn <recwarn>` fixture,
187+
no warning will be displayed at all.
188+
184189
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
185190
(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
186191
those warnings.
@@ -197,6 +202,9 @@ For example:
197202
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
198203
the regular expression ``".*U.*mode is deprecated"``.
199204

205+
See :ref:`@pytest.mark.filterwarnings <filterwarnings>` and
206+
:ref:`Controlling warnings <controlling-warnings>` for more examples.
207+
200208
.. note::
201209

202210
If warnings are configured at the interpreter level, using
@@ -245,10 +253,10 @@ when called with a ``17`` argument.
245253
Asserting warnings with the warns function
246254
------------------------------------------
247255

248-
249-
250256
You can check that code raises a particular warning using :func:`pytest.warns`,
251-
which works in a similar manner to :ref:`raises <assertraises>`:
257+
which works in a similar manner to :ref:`raises <assertraises>` (except that
258+
:ref:`raises <assertraises>` does not capture all exceptions, only the
259+
``expected_exception``):
252260

253261
.. code-block:: python
254262
@@ -261,8 +269,8 @@ which works in a similar manner to :ref:`raises <assertraises>`:
261269
with pytest.warns(UserWarning):
262270
warnings.warn("my warning", UserWarning)
263271
264-
The test will fail if the warning in question is not raised. The keyword
265-
argument ``match`` to assert that the exception matches a text or regex::
272+
The test will fail if the warning in question is not raised. Use the keyword
273+
argument ``match`` to assert that the warning matches a text or regex::
266274

267275
>>> with warns(UserWarning, match='must be 0 or None'):
268276
... warnings.warn("value must be 0 or None", UserWarning)
@@ -359,20 +367,32 @@ Additional use cases of warnings in tests
359367

360368
Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them:
361369

362-
- To ensure that **at least one** warning is emitted, use:
370+
- To ensure that **at least one** of the indicated warnings is issued, use:
363371

364372
.. code-block:: python
365373
366-
with pytest.warns():
374+
def test_warning():
375+
with pytest.warns((RuntimeWarning, UserWarning)):
376+
...
377+
378+
- To ensure that **only** certain warnings are issued, use:
379+
380+
.. code-block:: python
381+
382+
def test_warning(recwarn):
367383
...
384+
assert len(recwarn) == 1
385+
user_warning = recwarn.pop(UserWarning)
386+
assert issubclass(user_warning.category, UserWarning)
368387
369388
- To ensure that **no** warnings are emitted, use:
370389

371390
.. code-block:: python
372391
373-
with warnings.catch_warnings():
374-
warnings.simplefilter("error")
375-
...
392+
def test_warning():
393+
with warnings.catch_warnings():
394+
warnings.simplefilter("error")
395+
...
376396
377397
- To suppress warnings, use:
378398

src/_pytest/recwarn.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,15 @@ def warns(
110110
) -> Union["WarningsChecker", Any]:
111111
r"""Assert that code raises a particular class of warning.
112112
113-
Specifically, the parameter ``expected_warning`` can be a warning class or
114-
sequence of warning classes, and the code inside the ``with`` block must issue a warning of that class or
115-
classes.
113+
Specifically, the parameter ``expected_warning`` can be a warning class or sequence
114+
of warning classes, and the code inside the ``with`` block must issue at least one
115+
warning of that class or classes.
116116
117-
This helper produces a list of :class:`warnings.WarningMessage` objects,
118-
one for each warning raised.
117+
This helper produces a list of :class:`warnings.WarningMessage` objects, one for
118+
each warning raised (regardless of whether it is an ``expected_warning`` or not).
119119
120-
This function can be used as a context manager, or any of the other ways
121-
:func:`pytest.raises` can be used::
120+
This function can be used as a context manager, which will capture all the raised
121+
warnings inside it::
122122
123123
>>> import pytest
124124
>>> with pytest.warns(RuntimeWarning):
@@ -139,6 +139,11 @@ def warns(
139139
...
140140
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
141141
142+
**Using with** ``pytest.mark.parametrize``
143+
144+
When using :ref:`pytest.mark.parametrize ref` it is possible to parametrize tests
145+
such that some runs raise a warning and others do not.
146+
142147
"""
143148
__tracebackhide__ = True
144149
if not args:

0 commit comments

Comments
 (0)