Skip to content

Commit 0fb7cae

Browse files
authored
Merge pull request #13839 from bluetech/strict
Add `strict` configuration option to enable all other strictness options
2 parents a75b425 + d79af50 commit 0fb7cae

File tree

20 files changed

+242
-61
lines changed

20 files changed

+242
-61
lines changed

changelog/13823.feature.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Added a :confval:`strict` configuration option to enable all strictness-related options.
2+
3+
When set to ``True``, the :confval:`strict` option currently enables :confval:`strict_config`,
4+
:confval:`strict_markers`, :confval:`strict_xfail`, and :confval:`strict_parametrization_ids`.
5+
6+
The individual strictness options can be explicitly set to override the global :confval:`strict` setting.
7+
8+
If new strictness options are added in the future, they will also be automatically enabled by :confval:`strict`.
9+
Therefore, we only recommend setting ``strict=True`` if you're using a locked version of pytest,
10+
or if you want to proactively adopt new strictness options as they are added.

changelog/13823.improvement.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Added :confval:`strict_xfail` as an alias to the ``xfail_strict`` option,
2+
:confval:`strict_config` as an alias to the ``--strict-config`` flag,
3+
and :confval:`strict_markers` as an alias to the ``--strict-markers`` flag.
4+
This makes all strictness options consistently have configuration options with the prefix ``strict_``.

doc/en/deprecations.rst

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -589,18 +589,20 @@ removed in pytest 8 (deprecated since pytest 2.4.0):
589589
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
590590

591591

592-
The ``--strict`` command-line option
593-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
592+
The ``--strict`` command-line option (reintroduced)
593+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
594594

595595
.. deprecated:: 6.2
596-
.. versionremoved:: 8.0
596+
.. versionchanged:: 9.0
597597

598-
The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which
598+
The ``--strict`` command-line option had been deprecated in favor of ``--strict-markers``, which
599599
better conveys what the option does.
600600

601-
We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing
602-
flag for all strictness related options (``--strict-markers`` and ``--strict-config``
603-
at the moment, more might be introduced in the future).
601+
In version 8.1, we accidentally un-deprecated ``--strict``.
602+
603+
In version 9.0, we changed ``--strict`` to make it set the new :confval:`strict`
604+
configuration option. It now enables all strictness related options (including
605+
:confval:`strict_markers`).
604606

605607

606608
.. _cmdline-preparse-deprecated:

doc/en/example/markers.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,7 @@ For an example on how to add and work with markers from a plugin, see
286286

287287
* Asking for existing markers via ``pytest --markers`` gives good output
288288

289-
* Typos in function markers are treated as an error if you use
290-
the ``--strict-markers`` option.
289+
* Typos in function markers are treated as an error if you use the :confval:`strict_markers` configuration option.
291290

292291
.. _`scoped-marking`:
293292

doc/en/how-to/mark.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ surprising due to mistyped names. As described in the previous section, you can
8080
the warning for custom marks by registering them in your ``pytest.ini`` file or
8181
using a custom ``pytest_configure`` hook.
8282

83-
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
83+
When the :confval:`strict_markers` ini option is set, any unknown marks applied
8484
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error. You can
85-
enforce this validation in your project by adding ``--strict-markers`` to ``addopts``:
85+
enforce this validation in your project by setting :confval:`strict_markers` in your configuration:
8686

8787
.. code-block:: ini
8888
8989
[pytest]
90-
addopts = --strict-markers
90+
strict_markers = True
9191
markers =
9292
slow: marks tests as slow (deselect with '-m "not slow"')
9393
serial

doc/en/how-to/skipping.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,12 @@ You can change this by setting the ``strict`` keyword-only parameter to ``True``
331331
This will make ``XPASS`` ("unexpectedly passing") results from this test to fail the test suite.
332332

333333
You can change the default value of the ``strict`` parameter using the
334-
``xfail_strict`` ini option:
334+
``strict_xfail`` ini option:
335335

336336
.. code-block:: ini
337337
338338
[pytest]
339-
xfail_strict=true
339+
strict_xfail=true
340340
341341
342342
Ignoring xfail

doc/en/reference/reference.rst

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ pytest.mark.xfail
261261

262262
Marks a test function as *expected to fail*.
263263

264-
.. py:function:: pytest.mark.xfail(condition=False, *, reason=None, raises=None, run=True, strict=xfail_strict)
264+
.. py:function:: pytest.mark.xfail(condition=False, *, reason=None, raises=None, run=True, strict=strict_xfail)
265265
266266
:keyword Union[bool, str] condition:
267267
Condition for marking the test function as xfail (``True/False`` or a
@@ -286,7 +286,7 @@ Marks a test function as *expected to fail*.
286286
that are always failing and there should be a clear indication if they unexpectedly start to pass (for example
287287
a new release of a library fixes a known bug).
288288

289-
Defaults to :confval:`xfail_strict`, which is ``False`` by default.
289+
Defaults to :confval:`strict_xfail`, which is ``False`` by default.
290290

291291

292292
Custom marks
@@ -1774,25 +1774,21 @@ passed multiple times. The expected format is ``name=value``. For example::
17741774

17751775
.. confval:: markers
17761776

1777-
When the ``--strict-markers`` or ``--strict`` command-line arguments are used,
1777+
When the :confval:`strict_markers` configuration option is set,
17781778
only known markers - defined in code by core pytest or some plugin - are allowed.
17791779

17801780
You can list additional markers in this setting to add them to the whitelist,
1781-
in which case you probably want to add ``--strict-markers`` to ``addopts``
1781+
in which case you probably want to set :confval:`strict_markers` to ``True``
17821782
to avoid future regressions:
17831783

17841784
.. code-block:: ini
17851785
17861786
[pytest]
1787-
addopts = --strict-markers
1787+
strict_markers = True
17881788
markers =
17891789
slow
17901790
serial
17911791
1792-
.. note::
1793-
The use of ``--strict-markers`` is highly preferred. ``--strict`` was kept for
1794-
backward compatibility only and may be confusing for others as it only applies to
1795-
markers and not to other options.
17961792
17971793
.. confval:: minversion
17981794

@@ -2070,7 +2066,33 @@ passed multiple times. The expected format is ``name=value``. For example::
20702066
"auto" can be used to explicitly use the global verbosity level.
20712067

20722068

2073-
.. confval:: xfail_strict
2069+
.. confval:: strict
2070+
2071+
If set to ``True``, enables all strictness options:
2072+
2073+
* :confval:`strict_config`
2074+
* :confval:`strict_markers`
2075+
* :confval:`strict_xfail`
2076+
* :confval:`strict_parametrization_ids`
2077+
2078+
Plugins may also enable their own strictness options.
2079+
2080+
If you explicitly set an individual strictness option, it takes precedence over ``strict``.
2081+
2082+
.. note::
2083+
If new strictness options are added to pytest in the future, they will also be enabled by ``strict``.
2084+
We therefore only recommend using this option when using a locked version of pytest,
2085+
or if you want to proactively adopt new strictness options as they are added.
2086+
2087+
.. code-block:: ini
2088+
2089+
[pytest]
2090+
strict = True
2091+
2092+
.. versionadded:: 9.0
2093+
2094+
2095+
.. confval:: strict_xfail
20742096

20752097
If set to ``True``, tests marked with ``@pytest.mark.xfail`` that actually succeed will by default fail the
20762098
test suite.
@@ -2080,7 +2102,38 @@ passed multiple times. The expected format is ``name=value``. For example::
20802102
.. code-block:: ini
20812103
20822104
[pytest]
2083-
xfail_strict = True
2105+
strict_xfail = True
2106+
2107+
You can also enable this option via the :confval:`strict` option.
2108+
2109+
.. versionchanged:: 9.0
2110+
Renamed from ``xfail_strict`` to ``strict_xfail``.
2111+
``xfail_strict`` is accepted as an alias for ``strict_xfail``.
2112+
2113+
2114+
.. confval:: strict_config
2115+
2116+
If set to ``True``, any warnings encountered while parsing the ``pytest`` section of the configuration file will raise errors.
2117+
2118+
.. code-block:: ini
2119+
2120+
[pytest]
2121+
strict_config = True
2122+
2123+
You can also enable this option via the :confval:`strict` option.
2124+
2125+
2126+
.. confval:: strict_markers
2127+
2128+
If set to ``True``, markers not registered in the ``markers`` section of the configuration file will raise errors.
2129+
2130+
.. code-block:: ini
2131+
2132+
[pytest]
2133+
strict_markers = True
2134+
2135+
You can also enable this option via the :confval:`strict` option.
2136+
20842137

20852138
.. confval:: strict_parametrization_ids
20862139

@@ -2094,6 +2147,8 @@ passed multiple times. The expected format is ``name=value``. For example::
20942147
[pytest]
20952148
strict_parametrization_ids = True
20962149
2150+
You can also enable this option via the :confval:`strict` option.
2151+
20972152
For example,
20982153

20992154
.. code-block:: python

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ max_supported_python = "3.14"
355355

356356
[tool.pytest.ini_options]
357357
minversion = "2.0"
358-
addopts = "-rfEX -p pytester --strict-markers"
358+
addopts = "-rfEX -p pytester"
359359
python_files = [
360360
"test_*.py",
361361
"*_test.py",
@@ -378,8 +378,7 @@ norecursedirs = [
378378
"build",
379379
"dist",
380380
]
381-
xfail_strict = true
382-
strict_parametrization_ids = true
381+
strict = true
383382
filterwarnings = [
384383
"error",
385384
"default:Using or importing the ABCs:DeprecationWarning:unittest2.*",

src/_pytest/config/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,10 @@ def _validate_plugins(self) -> None:
15151515
)
15161516

15171517
def _warn_or_fail_if_strict(self, message: str) -> None:
1518-
if self.known_args_namespace.strict_config:
1518+
strict_config = self.getini("strict_config")
1519+
if strict_config is None:
1520+
strict_config = self.getini("strict")
1521+
if strict_config:
15191522
raise UsageError(message)
15201523

15211524
self.issue_config_time_warning(PytestConfigWarning(message), stacklevel=3)

src/_pytest/config/argparsing.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,3 +547,40 @@ def _split_lines(self, text, width):
547547
for line in text.splitlines():
548548
lines.extend(textwrap.wrap(line.strip(), width))
549549
return lines
550+
551+
552+
class OverrideIniAction(argparse.Action):
553+
"""Custom argparse action that makes a CLI flag equivalent to overriding an
554+
option, in addition to behaving like `store_true`.
555+
556+
This can simplify things since code only needs to inspect the ini option
557+
and not consider the CLI flag.
558+
"""
559+
560+
def __init__(
561+
self,
562+
option_strings: Sequence[str],
563+
dest: str,
564+
nargs: int | str | None = None,
565+
*args,
566+
ini_option: str,
567+
ini_value: str,
568+
**kwargs,
569+
) -> None:
570+
super().__init__(option_strings, dest, 0, *args, **kwargs)
571+
self.ini_option = ini_option
572+
self.ini_value = ini_value
573+
574+
def __call__(
575+
self,
576+
parser: argparse.ArgumentParser,
577+
namespace: argparse.Namespace,
578+
*args,
579+
**kwargs,
580+
) -> None:
581+
setattr(namespace, self.dest, True)
582+
current_overrides = getattr(namespace, "override_ini", None)
583+
if current_overrides is None:
584+
current_overrides = []
585+
current_overrides.append(f"{self.ini_option}={self.ini_value}")
586+
setattr(namespace, "override_ini", current_overrides)

0 commit comments

Comments
 (0)