@@ -7,14 +7,49 @@ pytest-dependency does not seem to behave as expected.
7
7
Example
8
8
-------
9
9
10
- Throughout this debugging guide, we will consider the following
11
- example:
10
+ We consider the following example in this guide:
12
11
13
12
.. literalinclude :: ../examples/debugging.py
14
13
14
+ This example contains several cases where the presumably intended
15
+ behavior of the code differs from what happens in practice. We will
16
+ show below how diagnostic tools in pytest may be used to unravel the
17
+ discrepancies. The results that may (or may not) be surprising
18
+ include:
19
+
20
+ + The test method `test_c ` in class `TestClass ` depending on `test_b `
21
+ is run, although the test method `test_b ` fails.
22
+
23
+ + All instances of `test_colors ` succeed. Yet `test_multicolored `
24
+ that only depends on `test_colors ` is skipped.
25
+
26
+ + Similarly `test_alert ` depending only on `test_colors[Color.RED] ` is
27
+ skipped, although `test_colors ` with the parameter value `Color.RED `
28
+ succeeds.
29
+
30
+ + `test_k ` depending only on `test_b ` is skipped, although `test_b `
31
+ succeeds.
32
+
33
+ + Same with `test_m ` depending only on `test_b ` is skipped.
34
+
35
+ + `test_o ` depending only on `test_h ` is skipped, although `test_h `
36
+ succeeds.
37
+
38
+ + `test_q ` depending only on `test_p ` is skipped, although `test_p `
39
+ succeeds.
40
+
41
+ + `test_r ` is run, although `test_a ` fails.
42
+
43
+ + `test_s ` depending only on `test_l ` is skipped, although `test_l `
44
+ succeeds.
45
+
15
46
Diagnostic tools
16
47
----------------
17
48
49
+ There are different ways to request diagnostic output from pytest. We
50
+ will discuss how they may be used to better understand the behavior of
51
+ pytest-dependency.
52
+
18
53
pytest summary
19
54
..............
20
55
@@ -23,6 +58,12 @@ skipped tests using the ``-rs`` `command line option`__:
23
58
24
59
.. literalinclude :: ../examples/debugging-summary.out
25
60
61
+ This summary indicates if a test has been skipped by pytest-dependency
62
+ in the first place. In the present example, the summary hints that
63
+ `test_k ` has been skipped due to another reason, unrelated to
64
+ pytest-dependency. If the test has been skipped by pytest-dependency,
65
+ the summary displays the name of the missing dependency.
66
+
26
67
.. __ : https://docs.pytest.org/en/stable/usage.html#detailed-summary-report
27
68
28
69
Verbose pytest output
@@ -33,14 +74,98 @@ you call pytest with the ``--verbose`` command line option:
33
74
34
75
.. literalinclude :: ../examples/debugging-verbose.out
35
76
77
+ The verbose listing is particular useful, because it shows the pytest
78
+ node id for each test, which is not always obvious. As explained in
79
+ Section :ref: `names `, this node id is the basis to form the default
80
+ test name that need to be used to reference the test in the
81
+ dependencies.
82
+
83
+ From this list we can understand why `test_multicolored ` has been
84
+ skipped: it depends on `test_colors `. But `test_colors ` is
85
+ parametrized and thus the parameter value is included in the node id.
86
+ As a result, a dependency by the name `test_colors ` can not be found.
87
+ The same thing happens in the case of `test_s `: it depends on
88
+ `test_l `, but the latter uses a parametrized fixture, so it indirectly
89
+ takes a parameter value and that value must be included in the
90
+ reference for the dependency.
91
+
92
+ In the case of `test_alert `, the parameter value is included in the
93
+ dependency `test_colors[Color.RED] `. But in the node id as displayed
94
+ in the verbose list, that test appears as `test_colors[RED] `. Note
95
+ that `class Color ` overrides the string representation operator and
96
+ that affects how the parameter value appears in the node id in this
97
+ case.
98
+
99
+ The verbose list also displays the execution order of the tests. In
100
+ the present example, this order differs from the order in the source
101
+ code. That is the reason why both instances of `test_q ` are skipped:
102
+ they are executed before the dependency `test_p `. So the outcome of
103
+ the latter is yet unknown at the moment that the dependency is
104
+ checked.
105
+
36
106
Logging
37
107
.......
38
108
39
109
pytest-dependency emits log messages when registering test results and
40
110
when checking dependencies for a test. You can request these log
41
111
messages to be displayed at runtime using `log command line options `__
42
- in the pytest call:
112
+ in the pytest call. Beware that this may produce a large amount of
113
+ output, even for medium size test suites. We will present only a few
114
+ fragments of the output here. Consider the start of that output,
115
+ covering the first test `test_a `:
116
+
117
+ .. literalinclude :: ../examples/debugging-logging.out
118
+ :end-before: debugging.py::test_b
119
+
120
+ It is shown how the test outcome for each of the three test phases
121
+ (setup, call, and teardown) is registered in pytest-dependency. It is
122
+ also shown which name is used to register the test outcome depending
123
+ on the scope.
124
+
125
+ Considering the relevant fragments of the output, we can check why
126
+ `TestClass::test_c ` is not skipped:
127
+
128
+ .. literalinclude :: ../examples/debugging-logging.out
129
+ :lines: 20-31,86-116
130
+
131
+ The dependency `test_b ` is checked in module scope. If that
132
+ dependency was meant to reference the method of the same class, it
133
+ would either need to be referenced as `test_b ` in class scope or as
134
+ `TestClass::test_b ` in module scope or as
135
+ `debugging.py::TestClass::test_b ` in session scope. The way it is
136
+ formulated in the example, it actually references the test function
137
+ `test_b `, which succeeds.
138
+
139
+ A similar case is `test_m `:
43
140
44
141
.. literalinclude :: ../examples/debugging-logging.out
142
+ :lines: 20-31,264-274
143
+
144
+ The dependency `test_b ` is checked in session scope. There is no test
145
+ that matches this name. If that dependency was mean to reference the
146
+ test function `test_b ` in the example, it would either need to be
147
+ referenced as `debugging.py::test_b ` in session scope or as `test_b `
148
+ in module scope.
149
+
150
+ A slightly different situation is given in the case of `test_o `:
151
+
152
+ .. literalinclude :: ../examples/debugging-logging.out
153
+ :lines: 190-201,276-286
154
+
155
+ In the :func: `pytest.mark.dependency ` marker for `test_h ` in the
156
+ example, the name is overridden as `h `. The outcome of that test is
157
+ registered using that name. It can thus not be found by the name
158
+ `test_h `.
159
+
160
+ Considering the case of `test_r `:
161
+
162
+ .. literalinclude :: ../examples/debugging-logging.out
163
+ :lines: 300-310
164
+
165
+ That test has no dependencies. The error in the example is that the
166
+ :func: `pytest.mark.dependency ` marker is applied twice to the test.
167
+ That doesn't work in pytest, only the last invocation is effective.
168
+ As a result, the second invocation setting a name, effectively clears
169
+ the dependency list that was set in the first invocation.
45
170
46
171
.. __ : https://docs.pytest.org/en/stable/logging.html#live-logs
0 commit comments