parent
771d3e8f4f
commit
254689ff83
|
@ -57,15 +57,15 @@ Marker revamp and iteration
|
||||||
|
|
||||||
.. versionadded:: 3.6
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to add markers, in a cumulative manner. As a result of the this, markers would unintendely be passed along class hierarchies in surprising ways plus the API for retriving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
|
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
|
||||||
|
|
||||||
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
|
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
|
||||||
|
|
||||||
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
|
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
|
||||||
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
|
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
|
||||||
|
|
||||||
On top of that markers where not accessible the same way for modules, classes, and functions/methods,
|
On top of that markers were not accessible the same way for modules, classes, and functions/methods.
|
||||||
in fact, markers where only accessible in functions, even if they where declared on classes/modules.
|
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
|
||||||
|
|
||||||
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with the initial design, providing :func:`_pytest.nodes.Node.iter_markers` method to iterate over markers in a consistent manner and reworking the internals, which solved great deal of problems with the initial design.
|
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with the initial design, providing :func:`_pytest.nodes.Node.iter_markers` method to iterate over markers in a consistent manner and reworking the internals, which solved great deal of problems with the initial design.
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ In general there are two scenarios on how markers should be handled:
|
||||||
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
|
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
|
||||||
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
|
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
|
||||||
|
|
||||||
In this case replace use ``Node.get_closest_marker(name)``:
|
In this case, use ``Node.get_closest_marker(name)``:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ In general there are two scenarios on how markers should be handled:
|
||||||
if marker:
|
if marker:
|
||||||
level = marker.args[0]
|
level = marker.args[0]
|
||||||
|
|
||||||
2. Marks compose additive. E.g. ``skipif(condition)`` marks means you just want to evaluate all of them,
|
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
|
||||||
order doesn't even matter. You probably want to think of your marks as a set here.
|
order doesn't even matter. You probably want to think of your marks as a set here.
|
||||||
|
|
||||||
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
|
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
|
||||||
|
@ -127,27 +127,27 @@ Here is a non-exhaustive list of issues fixed by the new implementation:
|
||||||
|
|
||||||
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
|
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
|
||||||
|
|
||||||
* markers stains on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
|
* Markers stain on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
|
||||||
|
|
||||||
* combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
|
* Combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
|
||||||
|
|
||||||
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
|
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
|
||||||
|
|
||||||
* marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
|
* Marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
|
||||||
|
|
||||||
* fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
|
* Fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
|
||||||
|
|
||||||
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
|
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
|
||||||
|
|
||||||
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
|
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
|
||||||
|
|
||||||
* remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
|
* Remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
|
||||||
|
|
||||||
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
|
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
|
||||||
|
|
||||||
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
|
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
|
||||||
|
|
||||||
* marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
|
* Marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
|
||||||
|
|
||||||
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
|
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue