From aeae183c757a72b97a1231f6ce389fd082b9e998 Mon Sep 17 00:00:00 2001 From: Olga Matoula Date: Sun, 9 Jan 2022 22:09:30 +0000 Subject: [PATCH 1/4] Add docs on pytest.warns(None) deprecation --- changelog/9404.doc.rst | 1 + doc/en/deprecations.rst | 27 ++++++++++++++++++++++++--- src/_pytest/deprecated.py | 5 ++++- testing/deprecated_test.py | 7 +++++-- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 changelog/9404.doc.rst diff --git a/changelog/9404.doc.rst b/changelog/9404.doc.rst new file mode 100644 index 00000000000..70e4c6d5899 --- /dev/null +++ b/changelog/9404.doc.rst @@ -0,0 +1 @@ +Added extra documentation on alternatives to common misuses of `pytest.warns(None)` ahead of its deprecation. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 6351d1f6e6a..455a252c701 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -221,11 +221,32 @@ Using ``pytest.warns(None)`` .. deprecated:: 7.0 -:func:`pytest.warns(None) ` is now deprecated because many people used -it to mean "this code does not emit warnings", but it actually had the effect of -checking that the code emits at least one warning of any type - like ``pytest.warns()`` +:func:`pytest.warns(None) ` is now deprecated because it was frequently misused. +Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` or ``pytest.warns(Warning)``. +If you are looking to: + +- ensure that **no** warnings are emitted, consider using + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("error") + +- suppress warnings, you could use + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + +- ensure that **any** warning is emitted, please use + +.. code-block:: python + + with pytest.warns(): + pass The ``--strict`` command-line option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index f68aea37e4d..2f7ab5bde44 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -89,7 +89,10 @@ WARNS_NONE_ARG = PytestRemovedIn8Warning( "Passing None to catch any warning has been deprecated, pass no arguments instead:\n" - " Replace pytest.warns(None) by simply pytest.warns()." + "Replace pytest.warns(None) by simply pytest.warns().\n" + "See https://docs.pytest.org/en/latest/deprecations.html" + "#using-pytest-warns-none" + " on asserting no warnings were emitted." ) KEYWORD_MSG_ARG = UnformattedWarning( diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index c316b074c4b..79fcee620d5 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -138,8 +138,11 @@ def test_warns_none_is_deprecated(): with pytest.warns( PytestDeprecationWarning, match=re.escape( - "Passing None to catch any warning has been deprecated, pass no arguments instead:\n " - "Replace pytest.warns(None) by simply pytest.warns()." + "Passing None to catch any warning has been deprecated, pass no arguments instead:\n" + "Replace pytest.warns(None) by simply pytest.warns().\n" + "See https://docs.pytest.org/en/latest/deprecations.html" + "#using-pytest-warns-none" + " on asserting no warnings were emitted." ), ): with pytest.warns(None): # type: ignore[call-overload] From e69f04e3ce4483596d63394053abe9669bf38b8d Mon Sep 17 00:00:00 2001 From: Olga Matoula Date: Wed, 12 Jan 2022 17:42:15 +0000 Subject: [PATCH 2/4] Add new section for common warnings use cases --- doc/en/deprecations.rst | 23 +---------------------- doc/en/how-to/capture-warnings.rst | 26 ++++++++++++++++++++++++++ src/_pytest/deprecated.py | 9 ++++----- testing/deprecated_test.py | 9 ++++----- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 455a252c701..358967faeab 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -225,28 +225,7 @@ Using ``pytest.warns(None)`` Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` or ``pytest.warns(Warning)``. -If you are looking to: - -- ensure that **no** warnings are emitted, consider using - -.. code-block:: python - - with warnings.catch_warnings(): - warnings.simplefilter("error") - -- suppress warnings, you could use - -.. code-block:: python - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - -- ensure that **any** warning is emitted, please use - -.. code-block:: python - - with pytest.warns(): - pass +See https://docs.pytest.org/en/latest/how-to/capture-warnings.html#additional-use-cases-of-warnings-in-tests for use cases. The ``--strict`` command-line option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 7e877b4d3da..5ae59b7f816 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -300,6 +300,32 @@ filter at the end of the test, so no global state is leaked. .. _recwarn: +Additional use cases of warnings in tests +----------------------------------------- + +Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them: + +- To ensure that **any** warning is emitted, use: + +.. code-block:: python + + with pytest.warns(): + pass + +- To ensure that **no** warnings are emitted, use: + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("error") + +- To suppress warnings, use: + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + Recording warnings ------------------ diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 2f7ab5bde44..55a09d4969e 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -88,11 +88,10 @@ ) WARNS_NONE_ARG = PytestRemovedIn8Warning( - "Passing None to catch any warning has been deprecated, pass no arguments instead:\n" - "Replace pytest.warns(None) by simply pytest.warns().\n" - "See https://docs.pytest.org/en/latest/deprecations.html" - "#using-pytest-warns-none" - " on asserting no warnings were emitted." + "Passing None has been deprecated.\n" + "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" + "#additional-use-cases-of-warnings-in-tests" + " for alternativesin common use cases." ) KEYWORD_MSG_ARG = UnformattedWarning( diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 79fcee620d5..2bebfe25f80 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -138,11 +138,10 @@ def test_warns_none_is_deprecated(): with pytest.warns( PytestDeprecationWarning, match=re.escape( - "Passing None to catch any warning has been deprecated, pass no arguments instead:\n" - "Replace pytest.warns(None) by simply pytest.warns().\n" - "See https://docs.pytest.org/en/latest/deprecations.html" - "#using-pytest-warns-none" - " on asserting no warnings were emitted." + "Passing None has been deprecated.\n" + "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" + "#additional-use-cases-of-warnings-in-tests" + " for alternativesin common use cases." ), ): with pytest.warns(None): # type: ignore[call-overload] From 51ea042162e46ecf7bba975ba2a5c89da04d11a9 Mon Sep 17 00:00:00 2001 From: Olga Matoula Date: Thu, 13 Jan 2022 18:06:03 +0000 Subject: [PATCH 3/4] Fix references for warnings use cases --- doc/en/deprecations.rst | 2 +- doc/en/how-to/capture-warnings.rst | 55 ++++++++++++++++-------------- src/_pytest/deprecated.py | 2 +- testing/deprecated_test.py | 2 +- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 358967faeab..0851341ba71 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -225,7 +225,7 @@ Using ``pytest.warns(None)`` Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` or ``pytest.warns(Warning)``. -See https://docs.pytest.org/en/latest/how-to/capture-warnings.html#additional-use-cases-of-warnings-in-tests for use cases. +See :ref:`warns-use-cases` for examples. The ``--strict`` command-line option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 5ae59b7f816..81f2ebd6ea5 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -300,32 +300,6 @@ filter at the end of the test, so no global state is leaked. .. _recwarn: -Additional use cases of warnings in tests ------------------------------------------ - -Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them: - -- To ensure that **any** warning is emitted, use: - -.. code-block:: python - - with pytest.warns(): - pass - -- To ensure that **no** warnings are emitted, use: - -.. code-block:: python - - with warnings.catch_warnings(): - warnings.simplefilter("error") - -- To suppress warnings, use: - -.. code-block:: python - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - Recording warnings ------------------ @@ -370,6 +344,35 @@ warnings, or index into it to get a particular recorded warning. Full API: :class:`~_pytest.recwarn.WarningsRecorder`. +.. _`warns use cases`: + +Additional use cases of warnings in tests +----------------------------------------- + +Here are some use cases involving warnings that often come up in tests, and suggestions on how to deal with them: + +- To ensure that **any** warning is emitted, use: + +.. code-block:: python + + with pytest.warns(): + pass + +- To ensure that **no** warnings are emitted, use: + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("error") + +- To suppress warnings, use: + +.. code-block:: python + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + + .. _custom_failure_messages: Custom failure messages diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 55a09d4969e..4534fbcab82 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -91,7 +91,7 @@ "Passing None has been deprecated.\n" "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" "#additional-use-cases-of-warnings-in-tests" - " for alternativesin common use cases." + " for alternatives in common use cases." ) KEYWORD_MSG_ARG = UnformattedWarning( diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 2bebfe25f80..a567201b222 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -141,7 +141,7 @@ def test_warns_none_is_deprecated(): "Passing None has been deprecated.\n" "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" "#additional-use-cases-of-warnings-in-tests" - " for alternativesin common use cases." + " for alternatives in common use cases." ), ): with pytest.warns(None): # type: ignore[call-overload] From 35d27d234665bc5d079bfea0a97e6333c21b7995 Mon Sep 17 00:00:00 2001 From: Olga Matoula Date: Thu, 13 Jan 2022 18:11:24 +0000 Subject: [PATCH 4/4] Fix reference link --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 0851341ba71..a667fc4ccdf 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -225,7 +225,7 @@ Using ``pytest.warns(None)`` Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` or ``pytest.warns(Warning)``. -See :ref:`warns-use-cases` for examples. +See :ref:`warns use cases` for examples. The ``--strict`` command-line option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~