|
11 | 11 | from ..compat import MappingMixin
|
12 | 12 | from ..compat import NOTSET
|
13 | 13 | from _pytest.outcomes import fail
|
| 14 | +from _pytest.warning_types import PytestWarning |
14 | 15 |
|
15 | 16 | EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
|
16 | 17 |
|
@@ -283,28 +284,37 @@ def test_function():
|
283 | 284 | on the ``test_function`` object. """
|
284 | 285 |
|
285 | 286 | _config = None
|
| 287 | + _markers = set() |
286 | 288 |
|
287 | 289 | def __getattr__(self, name):
|
288 | 290 | if name[0] == "_":
|
289 | 291 | raise AttributeError("Marker name must NOT start with underscore")
|
| 292 | + |
290 | 293 | 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 break your tests. See " |
| 299 | + "https://docs.pytest.org/en/latest/mark.html for details." % name, |
| 300 | + PytestWarning, |
| 301 | + ) |
| 302 | + if self._config.option.strict: |
| 303 | + fail("{!r} not a registered marker".format(name), pytrace=False) |
| 304 | + |
292 | 305 | return MarkDecorator(Mark(name, (), {}))
|
293 | 306 |
|
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! |
306 | 311 | 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) |
308 | 318 |
|
309 | 319 |
|
310 | 320 | MARK_GEN = MarkGenerator()
|
|
0 commit comments