Skip to content

Commit 204712c

Browse files
committed
Emit warning for unknown marks
1 parent 1e5bf5b commit 204712c

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

src/_pytest/mark/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ def pytest_collection_modifyitems(items, config):
146146

147147
def pytest_configure(config):
148148
config._old_mark_config = MARK_GEN._config
149-
if config.option.strict:
150-
MARK_GEN._config = config
149+
MARK_GEN._config = config
151150

152151
empty_parameterset = config.getini(EMPTY_PARAMETERSET_OPTION)
153152

src/_pytest/mark/structures.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ..compat import MappingMixin
1212
from ..compat import NOTSET
1313
from _pytest.outcomes import fail
14+
from _pytest.warning_types import PytestWarning
1415

1516
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
1617

@@ -283,28 +284,37 @@ def test_function():
283284
on the ``test_function`` object. """
284285

285286
_config = None
287+
_markers = set()
286288

287289
def __getattr__(self, name):
288290
if name[0] == "_":
289291
raise AttributeError("Marker name must NOT start with underscore")
292+
290293
if self._config is not None:
291-
self._check(name)
294+
self._update_markers(name)
295+
if name not in self._markers:
296+
warnings.warn(
297+
"Unknown mark %r. You can register custom marks to avoid this "
298+
"warning, without risking typos that silently break your tests. "
299+
"See https://docs.pytest.org/en/latest/mark.html for more detail.",
300+
PytestWarning,
301+
)
302+
if self._config.option.strict:
303+
fail("{!r} not a registered marker".format(name), pytrace=False)
304+
292305
return MarkDecorator(Mark(name, (), {}))
293306

294-
def _check(self, name):
295-
try:
296-
if name in self._markers:
297-
return
298-
except AttributeError:
299-
pass
300-
self._markers = values = set()
301-
for line in self._config.getini("markers"):
302-
marker = line.split(":", 1)[0]
303-
marker = marker.rstrip()
304-
x = marker.split("(", 1)[0]
305-
values.add(x)
307+
def _update_markers(self, name):
308+
# We store a set of registered markers as a performance optimisation,
309+
# but more could be added to `self._config` by other plugins at runtime.
310+
# If we see an unknown marker, we therefore update the set and try again!
306311
if name not in self._markers:
307-
fail("{!r} not a registered marker".format(name), pytrace=False)
312+
for line in self._config.getini("markers"):
313+
# example lines: "skipif(condition): skip the given test if..."
314+
# or "hypothesis: tests which use Hypothesis", so to get the
315+
# marker name we we split on both `:` and `(`.
316+
marker = line.split(":")[0].split("(")[0].strip()
317+
self._markers.add(marker)
308318

309319

310320
MARK_GEN = MarkGenerator()

0 commit comments

Comments
 (0)