Skip to content
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
3 changes: 3 additions & 0 deletions changelog/4724.deprecation.rst
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 7 additions & 0 deletions src/_pytest/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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"
Expand Down Expand Up @@ -87,3 +88,9 @@
"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.",
)
13 changes: 8 additions & 5 deletions src/_pytest/recwarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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
Expand Down Expand Up @@ -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)
Expand All @@ -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)


Expand Down
9 changes: 9 additions & 0 deletions testing/deprecated_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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")
Expand Down Expand Up @@ -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(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inception

PytestDeprecationWarning,
match=r"pytest.warns\(\) got unexpected keyword arguments: \['foo'\]",
):
pytest.warns(UserWarning, foo="hello")