From 2cd159e8c54e98cf431d0528eceb6d404c4a0d19 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 15 May 2018 21:35:27 -0300 Subject: [PATCH] Add section on how to update marks and add ref to the deprecation notice --- _pytest/deprecated.py | 5 ++-- doc/en/mark.rst | 55 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/_pytest/deprecated.py b/_pytest/deprecated.py index 2be6b7300..c85588d79 100644 --- a/_pytest/deprecated.py +++ b/_pytest/deprecated.py @@ -32,8 +32,9 @@ RESULT_LOG = ( ) MARK_INFO_ATTRIBUTE = RemovedInPytest4Warning( - "MarkInfo objects are deprecated as they contain the merged marks.\n" - "Please use node.iter_markers to iterate over markers correctly" + "MarkInfo objects are deprecated as they contain merged marks which are hard to deal with correctly.\n" + "Please use node.get_closest_marker(name) or node.iter_markers(name).\n" + "Docs: https://docs.pytest.org/en/latest/mark.html#updating-code" ) MARK_PARAMETERSET_UNPACKING = RemovedInPytest4Warning( diff --git a/doc/en/mark.rst b/doc/en/mark.rst index bd416479d..97b632330 100644 --- a/doc/en/mark.rst +++ b/doc/en/mark.rst @@ -28,8 +28,8 @@ which also serve as documentation. .. currentmodule:: _pytest.mark.structures .. autoclass:: Mark - :members: - :noindex: + :members: + :noindex: .. `marker-iteration` @@ -51,8 +51,57 @@ in fact, markers where only accessible in functions, even if they where declared 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. -Here is a non-exhaustive list of issues fixed by the new implementation: +Updating code +~~~~~~~~~~~~~ +The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object +which contains the merged name, ``*args`` and ``**kwargs**`` of all the markers which apply to that node. + +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. +``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)``: + + .. code-block:: python + + # replace this: + marker = item.get_marker('log_level') + if marker: + level = marker.args[0] + + # by this: + marker = item.get_closest_marker('log_level') + if marker: + level = marker.args[0] + +2. Marks compose additive. E.g. ``skipif(condition)`` marks means 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. + + In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually. + + .. code-block:: python + + # replace this + skipif = item.get_marker('skipif') + if skipif: + for condition in skipif.args: + # eval condition + + # by this: + for skipif in item.iter_markers('skipif): + condition = skipif.args[0] + # eval condition + + +If you are unsure or have any questions, please consider opening +`an issue `_. + +Related issues +~~~~~~~~~~~~~~ + +Here is a non-exhaustive list of issues fixed by the new implementation: * Marks don't pick up nested classes (`#199 `_).