Factory for :class:`MarkDecorator` objects - exposed as a ``pytest.mark`` singleton instance. Example:: import pytest @pytest.mark.slowtest def test_function(): pass applies a 'slowtest' :class:`Mark` on ``test_function``.
| 464 | |
| 465 | @final |
| 466 | class MarkGenerator: |
| 467 | """Factory for :class:`MarkDecorator` objects - exposed as |
| 468 | a ``pytest.mark`` singleton instance. |
| 469 | |
| 470 | Example:: |
| 471 | |
| 472 | import pytest |
| 473 | |
| 474 | @pytest.mark.slowtest |
| 475 | def test_function(): |
| 476 | pass |
| 477 | |
| 478 | applies a 'slowtest' :class:`Mark` on ``test_function``. |
| 479 | """ |
| 480 | |
| 481 | # See TYPE_CHECKING above. |
| 482 | if TYPE_CHECKING: |
| 483 | skip: _SkipMarkDecorator |
| 484 | skipif: _SkipifMarkDecorator |
| 485 | xfail: _XfailMarkDecorator |
| 486 | parametrize: _ParametrizeMarkDecorator |
| 487 | usefixtures: _UsefixturesMarkDecorator |
| 488 | filterwarnings: _FilterwarningsMarkDecorator |
| 489 | |
| 490 | def __init__(self, *, _ispytest: bool = False) -> None: |
| 491 | check_ispytest(_ispytest) |
| 492 | self._config: Optional[Config] = None |
| 493 | self._markers: Set[str] = set() |
| 494 | |
| 495 | def __getattr__(self, name: str) -> MarkDecorator: |
| 496 | """Generate a new :class:`MarkDecorator` with the given name.""" |
| 497 | if name[0] == "_": |
| 498 | raise AttributeError("Marker name must NOT start with underscore") |
| 499 | |
| 500 | if self._config is not None: |
| 501 | # We store a set of markers as a performance optimisation - if a mark |
| 502 | # name is in the set we definitely know it, but a mark may be known and |
| 503 | # not in the set. We therefore start by updating the set! |
| 504 | if name not in self._markers: |
| 505 | for line in self._config.getini("markers"): |
| 506 | # example lines: "skipif(condition): skip the given test if..." |
| 507 | # or "hypothesis: tests which use Hypothesis", so to get the |
| 508 | # marker name we split on both `:` and `(`. |
| 509 | marker = line.split(":")[0].split("(")[0].strip() |
| 510 | self._markers.add(marker) |
| 511 | |
| 512 | # If the name is not in the set of known marks after updating, |
| 513 | # then it really is time to issue a warning or an error. |
| 514 | if name not in self._markers: |
| 515 | if self._config.option.strict_markers or self._config.option.strict: |
| 516 | fail( |
| 517 | f"{name!r} not found in `markers` configuration option", |
| 518 | pytrace=False, |
| 519 | ) |
| 520 | |
| 521 | # Raise a specific error for common misspellings of "parametrize". |
| 522 | if name in ["parameterize", "parametrise", "parameterise"]: |
| 523 | __tracebackhide__ = True |
no outgoing calls