Skip to content

Commit fd679a2

Browse files
committed
Fix handling of dependency names
- handle names for pytest-dependency separately to match behavior of pytest-dependency - get rid of the regex match
1 parent 2013979 commit fd679a2

File tree

5 files changed

+117
-36
lines changed

5 files changed

+117
-36
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixes
6+
- fixed handling of names in dependencies - did not match the actual
7+
behavior of `pytest-dependency`
8+
59
## [Version 0.9.1](https://pypi.org/project/pytest-order/0.9.0/) (2020-11-11)
610
This is a bugfix only release.
711

pytest_order/__init__.py

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# -*- coding: utf-8 -*-
22
import os
3-
import re
43
import sys
54
from collections import OrderedDict
65
from warnings import warn
@@ -127,21 +126,26 @@ def full_name(item, name=None):
127126
return path + name
128127

129128

130-
def mark_binning(item, keys, start, end, before, after, unordered, alias):
129+
def mark_binning(item, keys, start, end, before, after, dep, unordered, alias):
131130
handled = False
132-
if ("dependency" in keys and
133-
(Settings.order_dependencies or "order" in keys)):
131+
if "dependency" in keys:
134132
# always order dependencies if an order mark is present
135133
# otherwise only if order-dependencies is set
136134
mark = item.get_closest_marker("dependency")
137-
dependent_mark = mark.kwargs.get("depends")
138-
if dependent_mark:
139-
for name in dependent_mark:
140-
after.setdefault(full_name(item, name), []).append(item)
141-
handled = True
135+
if Settings.order_dependencies or "order" in keys:
136+
dependent_mark = mark.kwargs.get("depends")
137+
if dependent_mark:
138+
for name in dependent_mark:
139+
dep.setdefault(name, []).append(item)
140+
handled = True
141+
# we always collect the names of the dependent items, because
142+
# we need them in both cases
142143
name_mark = mark.kwargs.get("name")
143-
if name_mark:
144-
alias[full_name(item, name_mark)] = full_name(item)
144+
# the default name in pytest-dependency is the last part of the nodeid
145+
if not name_mark:
146+
# in pytest < 4 the nodeid has an unwanted ::() part
147+
name_mark = item.nodeid.split("::", 1)[1].replace("::()", "")
148+
alias[name_mark] = full_name(item)
145149

146150
if "order" in keys:
147151
mark = item.get_closest_marker("order")
@@ -168,7 +172,8 @@ def mark_binning(item, keys, start, end, before, after, unordered, alias):
168172
elif before_mark:
169173
before.setdefault(full_name(item, before_mark), []).append(item)
170174
elif after_mark:
171-
after.setdefault(full_name(item, after_mark), []).append(item)
175+
after.setdefault(
176+
full_name(item, after_mark), []).append(item)
172177
handled = True
173178
if not handled:
174179
unordered.append(item)
@@ -177,10 +182,8 @@ def mark_binning(item, keys, start, end, before, after, unordered, alias):
177182

178183

179184
def insert_before(name, items, sort):
180-
regex_name = re.escape(name) + r"(:?\.\w+)?$"
181185
for pos, item in enumerate(sort):
182-
item_name = full_name(item)
183-
if re.match(regex_name, item_name):
186+
if name == full_name(item):
184187
for item_to_insert in items:
185188
if item_to_insert in sort:
186189
index = sort.index(item_to_insert)
@@ -197,10 +200,9 @@ def insert_before(name, items, sort):
197200

198201

199202
def insert_after(name, items, sort):
200-
regex_name = re.escape(name) + r"(:?\.\w+)?$"
201203
for pos, item in reversed(list(enumerate(sort))):
202204
item_name = full_name(item)
203-
if re.match(regex_name, item_name):
205+
if item_name == name:
204206
for item_to_insert in items:
205207
if item_to_insert in sort:
206208
index = sort.index(item_to_insert)
@@ -217,22 +219,24 @@ def insert_after(name, items, sort):
217219
def do_modify_items(items):
218220
before_item = {}
219221
after_item = {}
222+
dep_item = {}
220223
start_item = {}
221224
end_item = {}
222225
unordered_list = []
223226
alias_names = {}
224227

225228
for item in items:
226229
mark_binning(item, item.keywords.keys(), start_item, end_item,
227-
before_item, after_item, unordered_list, alias_names)
230+
before_item, after_item, dep_item,
231+
unordered_list, alias_names)
228232

229233
start_item = sorted(start_item.items())
230234
end_item = sorted(end_item.items())
231235

232236
sorted_list = sort_numbered_items(start_item, end_item, unordered_list)
233237

234238
still_left = 0
235-
length = len(before_item) + len(after_item)
239+
length = len(before_item) + len(after_item) + len(dep_item)
236240

237241
while still_left != length:
238242
still_left = length
@@ -245,13 +249,19 @@ def do_modify_items(items):
245249

246250
remove_labels = []
247251
for label, after in after_item.items():
248-
name = alias_names[label] if label in alias_names else label
249-
if insert_after(name, after, sorted_list):
252+
if insert_after(label, after, sorted_list):
250253
remove_labels.append(label)
251254
for label in remove_labels:
252255
del after_item[label]
253256

254-
length = len(before_item) + len(after_item)
257+
remove_labels = []
258+
for label, after in dep_item.items():
259+
if insert_after(alias_names.get(label), after, sorted_list):
260+
remove_labels.append(label)
261+
for label in remove_labels:
262+
del dep_item[label]
263+
264+
length = len(before_item) + len(after_item) + len(dep_item)
255265
if length:
256266
sys.stdout.write("WARNING: cannot execute test relative to others: ")
257267
for label, entry in before_item.items():
@@ -260,6 +270,9 @@ def do_modify_items(items):
260270
for label, entry in after_item.items():
261271
sys.stdout.write(label + " ")
262272
sorted_list += entry
273+
for label, entry in dep_item.items():
274+
sys.stdout.write(label + " ")
275+
sorted_list += entry
263276
sys.stdout.flush()
264277
print("enqueue them behind the others")
265278

tests/test_dependency.py

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ def test_ignore_order_with_dependency(item_names_for):
1616
tests_content = """
1717
import pytest
1818
19+
@pytest.mark.dependency()
1920
def test_a():
2021
pass
2122
22-
@pytest.mark.dependency(depends=['test_a'])
23+
@pytest.mark.dependency(depends=["test_a"])
2324
@pytest.mark.order("first")
2425
def test_b():
2526
pass
@@ -31,11 +32,12 @@ def test_order_with_dependency(item_names_for):
3132
tests_content = """
3233
import pytest
3334
34-
@pytest.mark.dependency(depends=['test_b'])
35+
@pytest.mark.dependency(depends=["test_b"])
3536
@pytest.mark.order("second")
3637
def test_a():
3738
pass
3839
40+
@pytest.mark.dependency()
3941
def test_b():
4042
pass
4143
"""
@@ -47,10 +49,11 @@ def ordered_test():
4749
yield """
4850
import pytest
4951
52+
@pytest.mark.dependency()
5053
def test_a():
5154
pass
5255
53-
@pytest.mark.dependency(depends=['test_a'])
56+
@pytest.mark.dependency(depends=["test_a"])
5457
def test_b():
5558
pass
5659
"""
@@ -71,10 +74,11 @@ def order_dependency_test():
7174
yield """
7275
import pytest
7376
74-
@pytest.mark.dependency(depends=['test_b'])
77+
@pytest.mark.dependency(depends=["test_b"])
7578
def test_a():
7679
pass
7780
81+
@pytest.mark.dependency()
7882
def test_b():
7983
pass
8084
"""
@@ -98,9 +102,11 @@ def multiple_dependencies_test():
98102
def test_a():
99103
pass
100104
105+
@pytest.mark.dependency()
101106
def test_b():
102107
pass
103108
109+
@pytest.mark.dependency()
104110
def test_c():
105111
pass
106112
"""
@@ -157,40 +163,99 @@ def test_dependency_in_class(item_names_for, order_dependencies):
157163
import pytest
158164
159165
class Test:
160-
@pytest.mark.dependency(depends=['test_c'])
166+
@pytest.mark.dependency(depends=["Test::test_c"])
161167
def test_a(self):
162168
assert True
163169
164-
@pytest.mark.dependency(depends=['test_c'])
170+
@pytest.mark.dependency(depends=["Test::test_c"])
165171
def test_b(self):
166172
assert True
167173
174+
@pytest.mark.dependency()
168175
def test_c(self):
169176
assert True
170177
"""
171178
assert item_names_for(tests_content) == ["test_c", "test_a", "test_b"]
172179

173180

181+
def test_unresolved_dependency_in_class(item_names_for, order_dependencies,
182+
capsys):
183+
tests_content = """
184+
import pytest
185+
186+
class Test:
187+
@pytest.mark.dependency(depends=["test_c"])
188+
def test_a(self):
189+
assert True
190+
191+
@pytest.mark.dependency(depends=["test_c"])
192+
def test_b(self):
193+
assert True
194+
195+
@pytest.mark.dependency()
196+
def test_c(self):
197+
assert True
198+
"""
199+
assert item_names_for(tests_content) == ["test_c", "test_a", "test_b"]
200+
out, err = capsys.readouterr()
201+
warning = ("cannot execute test relative to others: "
202+
"test_c enqueue them behind the others")
203+
assert warning in out
204+
205+
174206
def test_named_dependency_in_class(item_names_for, order_dependencies):
175207
tests_content = """
176208
import pytest
177209
178210
class Test:
179-
@pytest.mark.dependency(name='test_1', depends=['test_3'])
211+
@pytest.mark.dependency(name="test_1", depends=["test_3"])
180212
def test_a(self):
181213
assert True
182214
183-
@pytest.mark.dependency(name='test_2', depends=['test_3'])
215+
@pytest.mark.dependency(name="test_2", depends=["test_3"])
184216
def test_b(self):
185217
assert True
186218
187-
@pytest.mark.dependency(name='test_3')
219+
@pytest.mark.dependency(name="test_3")
188220
def test_c(self):
189221
assert True
190222
"""
191223
assert item_names_for(tests_content) == ["test_c", "test_a", "test_b"]
192224

193225

226+
def test_dependencies_in_classes(item_names_for, order_dependencies):
227+
tests_content = """
228+
import pytest
229+
230+
class TestA:
231+
@pytest.mark.dependency(depends=["test_2"])
232+
def test_a(self):
233+
assert True
234+
235+
@pytest.mark.dependency(depends=["TestB::test_e"])
236+
def test_b(self):
237+
assert True
238+
239+
def test_c(self):
240+
assert True
241+
242+
class TestB:
243+
@pytest.mark.dependency(name="test_2")
244+
def test_d(self):
245+
assert True
246+
247+
@pytest.mark.dependency()
248+
def test_e(self):
249+
assert True
250+
251+
def test_f(self):
252+
assert True
253+
"""
254+
assert item_names_for(tests_content) == [
255+
"test_c", "test_d", "test_a", "test_e", "test_b", "test_f"
256+
]
257+
258+
194259
def test_unknown_dependency(item_names_for, order_dependencies, capsys):
195260
tests_content = """
196261
import pytest
@@ -199,7 +264,7 @@ class Test:
199264
def test_a(self):
200265
assert True
201266
202-
@pytest.mark.dependency(depends=['test_3'])
267+
@pytest.mark.dependency(depends=["test_3"])
203268
def test_b(self):
204269
assert True
205270
@@ -209,6 +274,5 @@ def test_c(self):
209274
assert item_names_for(tests_content) == ["test_a", "test_c", "test_b"]
210275
out, err = capsys.readouterr()
211276
warning = ("cannot execute test relative to others: "
212-
"test_unknown_dependency.Test.test_3 "
213-
"enqueue them behind the others")
277+
"test_3 enqueue them behind the others")
214278
assert warning in out

tests/test_ordering.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ def test_relative_in_class(item_names_for):
425425
import pytest
426426
427427
class Test:
428-
@pytest.mark.order(after='test_b')
428+
@pytest.mark.order(after="test_b")
429429
def test_a(self):
430430
assert True
431431

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ deps =
2828
pytest{37,38,39,310,40,41,42,43}: pytest-xdist<1.28.0
2929
pytest{44,45,46,50,51,52,53,54}: pytest-xdist<2.0.0
3030
pytest{60,61}: pytest-xdist
31-
pytest{36,37}: pytest-dependency<0.5.0
31+
pytest{37}: pytest-dependency<0.5.0
3232
pytest{38,39,310,40,41,42,43,44,45,46,50,51,52,53,54,60,61}: pytest-dependency
3333
pytest{37,38,39,310,40,41,42,43,44,45,46,50,51,52,53,54,60,61}: pytest-mock
3434

0 commit comments

Comments
 (0)