From e276bd3332015977c2534c8dde39b49588aeb4ed Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 5 Feb 2019 19:14:02 -0200 Subject: [PATCH] pytest.warns emits a warning on unknown keyword arguments --- changelog/4724.deprecation.rst | 3 +++ src/_pytest/deprecated.py | 7 +++++++ src/_pytest/recwarn.py | 13 ++++++++----- testing/deprecated_test.py | 9 +++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 changelog/4724.deprecation.rst diff --git a/changelog/4724.deprecation.rst b/changelog/4724.deprecation.rst new file mode 100644 index 000000000..6dc2fe98c --- /dev/null +++ b/changelog/4724.deprecation.rst @@ -0,0 +1,3 @@ +``pytest.warns()`` now emits a warning when it receives unknown keyword arguments. + +This will be changed into an error in the future. diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 494a453b6..4afde6902 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -14,6 +14,7 @@ from __future__ import print_function from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import RemovedInPytest4Warning +from _pytest.warning_types import UnformattedWarning YIELD_TESTS = "yield tests were removed in pytest 4.0 - {name} will be ignored" @@ -87,3 +88,9 @@ PYTEST_LOGWARNING = PytestDeprecationWarning( "pytest_logwarning is deprecated, no longer being called, and will be removed soon\n" "please use pytest_warning_captured instead" ) + +PYTEST_WARNS_UNKNOWN_KWARGS = UnformattedWarning( + PytestDeprecationWarning, + "pytest.warns() got unexpected keyword arguments: {args!r}.\n" + "This will be an error in future versions.", +) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index a58c75d3a..3e2ec86de 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -11,6 +11,7 @@ import warnings import six import _pytest._code +from _pytest.deprecated import PYTEST_WARNS_UNKNOWN_KWARGS from _pytest.deprecated import WARNS_EXEC from _pytest.fixtures import yield_fixture from _pytest.outcomes import fail @@ -84,10 +85,12 @@ def warns(expected_warning, *args, **kwargs): """ __tracebackhide__ = True - match_expr = None if not args: - if "match" in kwargs: - match_expr = kwargs.pop("match") + match_expr = kwargs.pop("match", None) + if kwargs: + warnings.warn( + PYTEST_WARNS_UNKNOWN_KWARGS.format(args=sorted(kwargs)), stacklevel=2 + ) return WarningsChecker(expected_warning, match_expr=match_expr) elif isinstance(args[0], str): warnings.warn(WARNS_EXEC, stacklevel=2) @@ -97,12 +100,12 @@ def warns(expected_warning, *args, **kwargs): loc = frame.f_locals.copy() loc.update(kwargs) - with WarningsChecker(expected_warning, match_expr=match_expr): + with WarningsChecker(expected_warning): code = _pytest._code.Source(code).compile() six.exec_(code, frame.f_globals, loc) else: func = args[0] - with WarningsChecker(expected_warning, match_expr=match_expr): + with WarningsChecker(expected_warning): return func(*args[1:], **kwargs) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 92cfcbff8..5db3cceed 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -6,6 +6,7 @@ import os import sys import pytest +from _pytest.warning_types import PytestDeprecationWarning from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG pytestmark = pytest.mark.pytester_example_path("deprecated") @@ -238,3 +239,11 @@ def test_python_deprecation(testdir): ) else: assert msg not in result.stdout.str() + + +def test_pytest_warns_unknown_kwargs(): + with pytest.warns( + PytestDeprecationWarning, + match=r"pytest.warns\(\) got unexpected keyword arguments: \['foo'\]", + ): + pytest.warns(UserWarning, foo="hello")