Skip to content

Commit 8b4bd3a

Browse files
committed
Fixed placements of the warnings to be in fixture, changed warning message from using string concat to f-strings for more readability, and added a function in compat to grab default parameters and its values
1 parent 2d991b5 commit 8b4bd3a

File tree

4 files changed

+88
-14
lines changed

4 files changed

+88
-14
lines changed

Diff for: src/_pytest/compat.py

+15
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,21 @@ def get_default_arg_names(function: Callable[..., Any]) -> tuple[str, ...]:
173173
and p.default is not Parameter.empty
174174
)
175175

176+
# def check_default_arguments(func, nodeid):
177+
# """Check for default arguments in the function and issue warnings."""
178+
# sig = inspect.signature(func)
179+
# for param in sig.parameters.values():
180+
# if param.default is not param.empty:
181+
# function_name = func.__name__
182+
# async_default_arg_warn(nodeid, function_name, param)
183+
184+
def get_default_name_val(function: Callable[..., Any]) -> dict[str, Any]:
185+
sig = signature(function)
186+
return {
187+
param.name: param.default
188+
for param in sig.parameters.values()
189+
if param.default is not Parameter.empty
190+
}
176191

177192
_non_printable_ascii_translate_table = {
178193
i: f"\\x{i:02x}" for i in range(128) if i not in range(32, 127)

Diff for: src/_pytest/fixtures.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from _pytest._code.code import TerminalRepr
4242
from _pytest._io import TerminalWriter
4343
from _pytest.compat import _PytestWrapper
44+
from _pytest.compat import get_default_name_val
4445
from _pytest.compat import assert_never
4546
from _pytest.compat import get_real_func
4647
from _pytest.compat import get_real_method
@@ -70,7 +71,7 @@
7071
from _pytest.scope import _ScopeName
7172
from _pytest.scope import HIGH_SCOPES
7273
from _pytest.scope import Scope
73-
from _pytest.warning_types import PytestRemovedIn9Warning
74+
from _pytest.warning_types import PytestDefaultArgumentWarning, PytestRemovedIn9Warning
7475
from _pytest.warning_types import PytestWarning
7576

7677

@@ -1448,6 +1449,20 @@ def deduplicate_names(*seqs: Iterable[str]) -> tuple[str, ...]:
14481449
return tuple(dict.fromkeys(name for seq in seqs for name in seq))
14491450

14501451

1452+
def default_arg_warn(nodeid: str, function_name, param_name, param_val) -> None:
1453+
msg = (
1454+
f"Test function '{function_name}' has a default argument '{param_name}={param_val}'.\n"
1455+
)
1456+
warnings.simplefilter("always", PytestDefaultArgumentWarning)
1457+
warnings.warn(PytestDefaultArgumentWarning(msg))
1458+
1459+
1460+
def check_default_arguments(func_name, default_args, nodeid):
1461+
"""Check for default arguments in the function and issue warnings."""
1462+
for arg_name, default_val in default_args.items():
1463+
default_arg_warn(nodeid, func_name, arg_name, default_val)
1464+
1465+
14511466
class FixtureManager:
14521467
"""pytest fixture definitions and information is stored and managed
14531468
from this class.
@@ -1528,6 +1543,11 @@ def getfixtureinfo(
15281543
ignore_args=direct_parametrize_args,
15291544
)
15301545

1546+
if func is not None:
1547+
function_name = func.__name__
1548+
default_args = get_default_name_val(func)
1549+
check_default_arguments(function_name, default_args, node.nodeid)
1550+
15311551
return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs)
15321552

15331553
def pytest_plugin_registered(self, plugin: _PluggyPlugin, plugin_name: str) -> None:

Diff for: src/_pytest/python.py

-13
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,9 @@ def async_fail(nodeid: str) -> None:
143143
fail(msg, pytrace=False)
144144

145145

146-
def async_default_arg_warn(nodeid: str, function_name, param) -> None:
147-
msg = (
148-
"Test function '" + function_name + "' has a default argument '" + param.name + "=" + str(param.default) + "'.\n"
149-
)
150-
warnings.simplefilter("always", PytestDefaultArgumentWarning)
151-
warnings.warn(PytestDefaultArgumentWarning(msg))
152-
153-
154146
@hookimpl(trylast=True)
155147
def pytest_pyfunc_call(pyfuncitem: Function) -> object | None:
156148
testfunction = pyfuncitem.obj
157-
sig = inspect.signature(testfunction)
158-
for param in sig.parameters.values():
159-
if param.default is not param.empty:
160-
function_name = testfunction.__name__
161-
async_default_arg_warn(pyfuncitem.nodeid, function_name, param)
162149

163150
if is_async_function(testfunction):
164151
async_fail(pyfuncitem.nodeid)

Diff for: testing/test_default_params.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from _pytest.pytester import Pytester
2+
3+
def test_no_default_argument(pytester: Pytester) -> None:
4+
pytester.makepyfile(
5+
"""
6+
def test_with_default_param(param):
7+
assert param == 42
8+
"""
9+
)
10+
result = pytester.runpytest()
11+
result.stdout.fnmatch_lines([
12+
"*fixture 'param' not found*"
13+
])
14+
15+
16+
def test_default_argument_warning(pytester: Pytester) -> None:
17+
pytester.makepyfile(
18+
"""
19+
def test_with_default_param(param=42):
20+
assert param == 42
21+
"""
22+
)
23+
result = pytester.runpytest()
24+
result.stdout.fnmatch_lines([
25+
"*PytestDefaultArgumentWarning: Test function 'test_with_default_param' has a default argument 'param=42'.*"
26+
])
27+
28+
29+
def test_no_warning_for_no_default_param(pytester: Pytester) -> None:
30+
pytester.makepyfile(
31+
"""
32+
def test_without_default_param(param):
33+
assert param is None
34+
"""
35+
)
36+
result = pytester.runpytest()
37+
assert "PytestDefaultArgumentWarning" not in result.stdout.str()
38+
39+
40+
def test_warning_for_multiple_default_params(pytester: Pytester) -> None:
41+
pytester.makepyfile(
42+
"""
43+
def test_with_multiple_defaults(param1=42, param2="default"):
44+
assert param1 == 42
45+
assert param2 == "default"
46+
"""
47+
)
48+
result = pytester.runpytest()
49+
result.stdout.fnmatch_lines([
50+
"*PytestDefaultArgumentWarning: Test function 'test_with_multiple_defaults' has a default argument 'param1=42'.*",
51+
"*PytestDefaultArgumentWarning: Test function 'test_with_multiple_defaults' has a default argument 'param2=default'.*"
52+
])

0 commit comments

Comments
 (0)