Skip to content

Commit 10f9e61

Browse files
committed
Add detailed discussion of the example in the debugging guide
1 parent 58ff4ff commit 10f9e61

File tree

1 file changed

+128
-3
lines changed

1 file changed

+128
-3
lines changed

doc/src/debugging.rst

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,49 @@ pytest-dependency does not seem to behave as expected.
77
Example
88
-------
99

10-
Throughout this debugging guide, we will consider the following
11-
example:
10+
We consider the following example in this guide:
1211

1312
.. literalinclude:: ../examples/debugging.py
1413

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+
1546
Diagnostic tools
1647
----------------
1748

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+
1853
pytest summary
1954
..............
2055

@@ -23,6 +58,12 @@ skipped tests using the ``-rs`` `command line option`__:
2358

2459
.. literalinclude:: ../examples/debugging-summary.out
2560

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+
2667
.. __: https://docs.pytest.org/en/stable/usage.html#detailed-summary-report
2768

2869
Verbose pytest output
@@ -33,14 +74,98 @@ you call pytest with the ``--verbose`` command line option:
3374

3475
.. literalinclude:: ../examples/debugging-verbose.out
3576

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+
36106
Logging
37107
.......
38108

39109
pytest-dependency emits log messages when registering test results and
40110
when checking dependencies for a test. You can request these log
41111
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`:
43140

44141
.. 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.
45170

46171
.. __: https://docs.pytest.org/en/stable/logging.html#live-logs

0 commit comments

Comments
 (0)