diff --git a/changelog/7620.bugfix.rst b/changelog/7620.bugfix.rst new file mode 100644 index 00000000000..d99cc202785 --- /dev/null +++ b/changelog/7620.bugfix.rst @@ -0,0 +1,3 @@ +It is now possible to silence :class:`pytest.PytestConfigWarning` messages about unknown configuration keys by using :confval:`filterwarnings`. + +Also, multiple keys are combined in a single warning, instead of showing a separate warning per key. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 453dd834537..f0cc38914ed 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1127,7 +1127,12 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None: ) else: raise - self._validate_keys() + + @hookimpl(hookwrapper=True) + def pytest_collection(self): + """Validate invalid ini keys after collection is done.""" + yield + self._validate_config_keys() def _checkversion(self) -> None: import pytest @@ -1148,9 +1153,13 @@ def _checkversion(self) -> None: % (self.inifile, minver, pytest.__version__,) ) - def _validate_keys(self) -> None: - for key in sorted(self._get_unknown_ini_keys()): - self._warn_or_fail_if_strict("Unknown config ini key: {}\n".format(key)) + def _validate_config_keys(self) -> None: + keys = sorted(self._get_unknown_ini_keys()) + if keys: + noun = "key" if len(keys) == 1 else "keys" + self._warn_or_fail_if_strict( + "Unknown config {}: {}".format(noun, ", ".join(keys)) + ) def _validate_plugins(self) -> None: required_plugins = sorted(self.getini("required_plugins")) @@ -1185,14 +1194,11 @@ def _validate_plugins(self) -> None: ) def _warn_or_fail_if_strict(self, message: str) -> None: + """Issue a PytestConfigWarning or fail if --strict-config was given""" if self.known_args_namespace.strict_config: fail(message, pytrace=False) - from _pytest.warnings import _issue_warning_captured - - _issue_warning_captured( - PytestConfigWarning(message), self.hook, stacklevel=3, - ) + warnings.warn(PytestConfigWarning(message)) def _get_unknown_ini_keys(self) -> List[str]: parser_inicfg = self._parser._inidict diff --git a/testing/test_config.py b/testing/test_config.py index 346edb3304c..35ffcf1b152 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -183,10 +183,9 @@ def test_confcutdir(self, testdir): ["unknown_ini", "another_unknown_ini"], [ "=*= warnings summary =*=", - "*PytestConfigWarning:*Unknown config ini key: another_unknown_ini", - "*PytestConfigWarning:*Unknown config ini key: unknown_ini", + "*PytestConfigWarning:*Unknown config keys: another_unknown_ini, unknown_ini", ], - "Unknown config ini key: another_unknown_ini", + "Unknown config keys: another_unknown_ini, unknown_ini", ), ( """ @@ -197,9 +196,9 @@ def test_confcutdir(self, testdir): ["unknown_ini"], [ "=*= warnings summary =*=", - "*PytestConfigWarning:*Unknown config ini key: unknown_ini", + "*PytestConfigWarning:*Unknown config key: unknown_ini", ], - "Unknown config ini key: unknown_ini", + "Unknown config key: unknown_ini", ), ( """ @@ -232,6 +231,7 @@ def test_confcutdir(self, testdir): ), ], ) + @pytest.mark.filterwarnings("default") def test_invalid_ini_keys( self, testdir, ini_file_text, invalid_keys, warning_output, exception_text ): @@ -250,10 +250,21 @@ def pytest_addoption(parser): result.stdout.fnmatch_lines(warning_output) if exception_text: - with pytest.raises(pytest.fail.Exception, match=exception_text): - testdir.runpytest("--strict-config") - else: - testdir.runpytest("--strict-config") + result = testdir.runpytest("--strict-config") + result.stdout.fnmatch_lines("INTERNALERROR>*" + exception_text) + + @pytest.mark.filterwarnings("default") + def test_silence_unknown_key_warning(self, testdir): + testdir.makeini( + """ + [pytest] + filterwarnings = + ignore:Unknown config key:pytest.PytestConfigWarning + foobar=1 + """ + ) + result = testdir.runpytest() + result.stdout.no_fnmatch_line("*PytestConfigWarning*") @pytest.mark.parametrize( "ini_file_text, exception_text",