You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .github/PULL_REQUEST_TEMPLATE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,12 +5,12 @@ Here's a quick checklist that should be present in PRs.
5
5
(please delete this text from the final description, this is just a guideline)
6
6
-->
7
7
8
-
-[ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
9
8
-[ ] Target the `master` branch for bug fixes, documentation updates and trivial changes.
10
9
-[ ] Target the `features` branch for new features and removals/deprecations.
11
10
-[ ] Include documentation when adding new features.
12
11
-[ ] Include new tests or update existing tests when applicable.
13
12
14
13
Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
15
14
15
+
-[ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
16
16
-[ ] Add yourself to `AUTHORS` in alphabetical order;
Copy file name to clipboardExpand all lines: doc/en/historical-notes.rst
+111Lines changed: 111 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,117 @@ Historical Notes
4
4
This page lists features or behavior from previous versions of pytest which have changed over the years. They are
5
5
kept here as a historical note so users looking at old code can find documentation related to them.
6
6
7
+
8
+
.. _marker-revamp:
9
+
10
+
Marker revamp and iteration
11
+
---------------------------
12
+
13
+
.. versionchanged:: 3.6
14
+
15
+
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``.
16
+
17
+
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.
18
+
19
+
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
20
+
``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.
21
+
22
+
On top of that markers were not accessible in the same way for modules, classes, and functions/methods.
23
+
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
24
+
25
+
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with
26
+
the initial design, providing the :func:`_pytest.nodes.Node.iter_markers` method to iterate over
27
+
markers in a consistent manner and reworking the internals, which solved a great deal of problems
28
+
with the initial design.
29
+
30
+
31
+
.. _update marker code:
32
+
33
+
Updating code
34
+
~~~~~~~~~~~~~
35
+
36
+
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
37
+
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
38
+
39
+
In general there are two scenarios on how markers should be handled:
40
+
41
+
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
42
+
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
43
+
44
+
In this case, use ``Node.get_closest_marker(name)``:
45
+
46
+
.. code-block:: python
47
+
48
+
# replace this:
49
+
marker = item.get_marker("log_level")
50
+
if marker:
51
+
level = marker.args[0]
52
+
53
+
# by this:
54
+
marker = item.get_closest_marker("log_level")
55
+
if marker:
56
+
level = marker.args[0]
57
+
58
+
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
59
+
order doesn't even matter. You probably want to think of your marks as a set here.
60
+
61
+
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
62
+
63
+
.. code-block:: python
64
+
65
+
# replace this
66
+
skipif = item.get_marker("skipif")
67
+
if skipif:
68
+
for condition in skipif.args:
69
+
# eval condition
70
+
...
71
+
72
+
# by this:
73
+
for skipif in item.iter_markers("skipif"):
74
+
condition = skipif.args[0]
75
+
# eval condition
76
+
77
+
78
+
If you are unsure or have any questions, please consider opening
@@ -15,151 +15,64 @@ some builtin markers, for example:
15
15
to the same test function.
16
16
17
17
It's easy to create custom markers or to apply markers
18
-
to whole test classes or modules. See :ref:`mark examples` for examples
19
-
which also serve as documentation.
18
+
to whole test classes or modules. Those markers can be used by plugins, and also
19
+
are commonly used to :ref:`select tests <mark run>` on the command-line with the ``-m`` option.
20
+
21
+
See :ref:`mark examples` for examples which also serve as documentation.
20
22
21
23
.. note::
22
24
23
25
Marks can only be applied to tests, having no effect on
24
26
:ref:`fixtures <fixtures>`.
25
27
26
28
27
-
.. _unknown-marks:
28
-
29
-
Raising errors on unknown marks
30
-
-------------------------------
29
+
Registering marks
30
+
-----------------
31
31
32
-
Unknown marks applied with the ``@pytest.mark.name_of_the_mark`` decorator
33
-
will always emit a warning, in order to avoid silently doing something
34
-
surprising due to mis-typed names. You can disable the warning for custom
35
-
marks by registering them in ``pytest.ini`` like this:
32
+
You can register custom marks in your ``pytest.ini`` file like this:
36
33
37
34
.. code-block:: ini
38
35
39
36
[pytest]
40
37
markers =
41
-
slow
38
+
slow: marks tests as slow (deselect with '-m "not slow"')
42
39
serial
43
40
44
-
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
45
-
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error.
46
-
Marks added by pytest or by a plugin instead of the decorator will not trigger
47
-
this error. To enforce validation of markers, add ``--strict-markers`` to ``addopts``:
48
-
49
-
.. code-block:: ini
50
-
51
-
[pytest]
52
-
addopts = --strict-markers
53
-
markers =
54
-
slow
55
-
serial
56
-
57
-
Third-party plugins should always :ref:`register their markers <registering-markers>`
58
-
so that they appear in pytest's help text and do not emit warnings.
59
-
60
-
61
-
.. _marker-revamp:
62
-
63
-
Marker revamp and iteration
64
-
---------------------------
65
-
66
-
67
-
68
-
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``.
69
-
70
-
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.
71
-
72
-
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
73
-
``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.
74
-
75
-
On top of that markers were not accessible the same way for modules, classes, and functions/methods.
76
-
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
77
-
78
-
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.
79
-
80
-
81
-
.. _update marker code:
82
-
83
-
Updating code
84
-
~~~~~~~~~~~~~
85
-
86
-
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
87
-
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
88
-
89
-
In general there are two scenarios on how markers should be handled:
41
+
Note that everything after the ``:`` is an optional description.
90
42
91
-
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
92
-
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
43
+
Alternatively, you can register new markers programatically in a
0 commit comments