Skip to content

Commit faba4b9

Browse files
committed
Fix handling of relative markers in classes
- class namespace had not been handled - fixed handling of dependencies (had been added to unordered entries)
1 parent c4b32ce commit faba4b9

File tree

4 files changed

+189
-76
lines changed

4 files changed

+189
-76
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixes
6+
- fixed handling of relative markers in classes
7+
- fixed handling of dependencies (could have been added twice)
8+
59
## [Version 0.9.0](https://pypi.org/project/pytest-order/0.9.0/) (2020-11-08)
610
This is the last major version that will support Python 2 - Python 2 support
711
will be dropped in version 1.0. There is no timeline for that release, as there

pytest_order/__init__.py

+31-28
Original file line numberDiff line numberDiff line change
@@ -112,29 +112,36 @@ def initialize(cls, config):
112112
cls.scope = "session"
113113

114114

115-
def get_filename(item):
116-
name = item.location[0]
117-
if os.sep in name:
118-
name = item.location[0].rsplit(os.sep, 1)[1]
119-
return name[:-3]
115+
def full_name(item, name=None):
116+
if name and "." in name:
117+
# assume it is already qualified
118+
return name
119+
path = item.location[0]
120+
if os.sep in path:
121+
path = item.location[0].rsplit(os.sep, 1)[1]
122+
path = path[:-3] + "."
123+
if name is None:
124+
return path + item.location[2]
125+
if "." in item.location[2]:
126+
path += item.location[2].rsplit(".", 1)[0] + "."
127+
return path + name
120128

121129

122130
def mark_binning(item, keys, start, end, before, after, unordered, alias):
131+
handled = False
123132
if ("dependency" in keys and
124133
(Settings.order_dependencies or "order" in keys)):
125134
# always order dependencies if an order mark is present
126135
# otherwise only if order-dependencies is set
127136
mark = item.get_closest_marker("dependency")
128-
prefix = get_filename(item) + "."
129137
dependent_mark = mark.kwargs.get("depends")
130138
if dependent_mark:
131139
for name in dependent_mark:
132-
if "." not in name:
133-
name = prefix + name
134-
after.setdefault(name, []).append(item)
140+
after.setdefault(full_name(item, name), []).append(item)
141+
handled = True
135142
name_mark = mark.kwargs.get("name")
136143
if name_mark:
137-
alias[prefix + name_mark] = prefix + item.name
144+
alias[full_name(item, name_mark)] = full_name(item)
138145

139146
if "order" in keys:
140147
mark = item.get_closest_marker("order")
@@ -150,33 +157,29 @@ def mark_binning(item, keys, start, end, before, after, unordered, alias):
150157
order = orders_map[order]
151158
else:
152159
warn("Unknown order attribute:'{}'".format(order))
153-
unordered.append(item)
154-
return False
160+
if not handled:
161+
unordered.append(item)
162+
return False
163+
return True
155164
if order < 0:
156165
end.setdefault(order, []).append(item)
157166
else:
158167
start.setdefault(order, []).append(item)
159168
elif before_mark:
160-
if "." not in before_mark:
161-
prefix = get_filename(item)
162-
before_mark = prefix + "." + before_mark
163-
before.setdefault(before_mark, []).append(item)
169+
before.setdefault(full_name(item, before_mark), []).append(item)
164170
elif after_mark:
165-
if "." not in after_mark:
166-
prefix = get_filename(item)
167-
after_mark = prefix + "." + after_mark
168-
169-
after.setdefault(after_mark, []).append(item)
170-
return True
171-
unordered.append(item)
172-
return False
171+
after.setdefault(full_name(item, after_mark), []).append(item)
172+
handled = True
173+
if not handled:
174+
unordered.append(item)
175+
return False
176+
return True
173177

174178

175179
def insert_before(name, items, sort):
176180
regex_name = re.escape(name) + r"(:?\.\w+)?$"
177181
for pos, item in enumerate(sort):
178-
prefix = get_filename(item)
179-
item_name = prefix + "." + item.location[2]
182+
item_name = full_name(item)
180183
if re.match(regex_name, item_name):
181184
for item_to_insert in items:
182185
if item_to_insert in sort:
@@ -196,7 +199,7 @@ def insert_before(name, items, sort):
196199
def insert_after(name, items, sort):
197200
regex_name = re.escape(name) + r"(:?\.\w+)?$"
198201
for pos, item in reversed(list(enumerate(sort))):
199-
item_name = get_filename(item) + "." + item.location[2]
202+
item_name = full_name(item)
200203
if re.match(regex_name, item_name):
201204
for item_to_insert in items:
202205
if item_to_insert in sort:
@@ -250,7 +253,7 @@ def do_modify_items(items):
250253

251254
length = len(before_item) + len(after_item)
252255
if length:
253-
sys.stdout.write("WARNING: can not execute test relative to others: ")
256+
sys.stdout.write("WARNING: cannot execute test relative to others: ")
254257
for label, entry in before_item.items():
255258
sys.stdout.write(label + " ")
256259
sorted_list += entry

tests/test_dependency.py

+105-43
Original file line numberDiff line numberDiff line change
@@ -14,45 +14,45 @@ def order_dependencies(ignore_settings):
1414

1515
def test_ignore_order_with_dependency(item_names_for):
1616
tests_content = """
17-
import pytest
17+
import pytest
1818
19-
def test_a():
20-
pass
19+
def test_a():
20+
pass
2121
22-
@pytest.mark.dependency(depends=['test_a'])
23-
@pytest.mark.order("first")
24-
def test_b():
25-
pass
22+
@pytest.mark.dependency(depends=['test_a'])
23+
@pytest.mark.order("first")
24+
def test_b():
25+
pass
2626
"""
2727
assert item_names_for(tests_content) == ["test_a", "test_b"]
2828

2929

3030
def test_order_with_dependency(item_names_for):
3131
tests_content = """
32-
import pytest
32+
import pytest
3333
34-
@pytest.mark.dependency(depends=['test_b'])
35-
@pytest.mark.order("second")
36-
def test_a():
37-
pass
34+
@pytest.mark.dependency(depends=['test_b'])
35+
@pytest.mark.order("second")
36+
def test_a():
37+
pass
3838
39-
def test_b():
40-
pass
39+
def test_b():
40+
pass
4141
"""
4242
assert item_names_for(tests_content) == ["test_b", "test_a"]
4343

4444

4545
@pytest.fixture(scope="module")
4646
def ordered_test():
4747
yield """
48-
import pytest
48+
import pytest
4949
50-
def test_a():
51-
pass
50+
def test_a():
51+
pass
5252
53-
@pytest.mark.dependency(depends=['test_a'])
54-
def test_b():
55-
pass
53+
@pytest.mark.dependency(depends=['test_a'])
54+
def test_b():
55+
pass
5656
"""
5757

5858

@@ -69,14 +69,14 @@ def test_dependency_already_ordered_with_ordering(ordered_test,
6969
@pytest.fixture(scope="module")
7070
def order_dependency_test():
7171
yield """
72-
import pytest
72+
import pytest
7373
74-
@pytest.mark.dependency(depends=['test_b'])
75-
def test_a():
76-
pass
74+
@pytest.mark.dependency(depends=['test_b'])
75+
def test_a():
76+
pass
7777
78-
def test_b():
79-
pass
78+
def test_b():
79+
pass
8080
"""
8181

8282

@@ -92,17 +92,17 @@ def test_order_dependency_ordered(order_dependency_test, item_names_for,
9292
@pytest.fixture(scope="module")
9393
def multiple_dependencies_test():
9494
yield """
95-
import pytest
95+
import pytest
9696
97-
@pytest.mark.dependency(depends=["test_b", "test_c"])
98-
def test_a():
99-
pass
97+
@pytest.mark.dependency(depends=["test_b", "test_c"])
98+
def test_a():
99+
pass
100100
101-
def test_b():
102-
pass
101+
def test_b():
102+
pass
103103
104-
def test_c():
105-
pass
104+
def test_c():
105+
pass
106106
"""
107107

108108

@@ -124,18 +124,18 @@ def test_order_multiple_dependencies_ordered(multiple_dependencies_test,
124124
@pytest.fixture(scope="module")
125125
def named_dependency_test():
126126
yield """
127-
import pytest
127+
import pytest
128128
129-
@pytest.mark.dependency(depends=["my_test"])
130-
def test_a():
131-
pass
129+
@pytest.mark.dependency(depends=["my_test"])
130+
def test_a():
131+
pass
132132
133-
@pytest.mark.dependency(name="my_test")
134-
def test_b():
135-
pass
133+
@pytest.mark.dependency(name="my_test")
134+
def test_b():
135+
pass
136136
137-
def test_c():
138-
pass
137+
def test_c():
138+
pass
139139
"""
140140

141141

@@ -150,3 +150,65 @@ def test_order_named_dependency_ordered(named_dependency_test,
150150
assert item_names_for(named_dependency_test) == [
151151
"test_b", "test_a", "test_c"
152152
]
153+
154+
155+
def test_dependency_in_class(item_names_for, order_dependencies):
156+
tests_content = """
157+
import pytest
158+
159+
class Test:
160+
@pytest.mark.dependency(depends=['test_c'])
161+
def test_a(self):
162+
assert True
163+
164+
@pytest.mark.dependency(depends=['test_c'])
165+
def test_b(self):
166+
assert True
167+
168+
def test_c(self):
169+
assert True
170+
"""
171+
assert item_names_for(tests_content) == ["test_c", "test_a", "test_b"]
172+
173+
174+
def test_named_dependency_in_class(item_names_for, order_dependencies):
175+
tests_content = """
176+
import pytest
177+
178+
class Test:
179+
@pytest.mark.dependency(name='test_1', depends=['test_3'])
180+
def test_a(self):
181+
assert True
182+
183+
@pytest.mark.dependency(name='test_2', depends=['test_3'])
184+
def test_b(self):
185+
assert True
186+
187+
@pytest.mark.dependency(name='test_3')
188+
def test_c(self):
189+
assert True
190+
"""
191+
assert item_names_for(tests_content) == ["test_c", "test_a", "test_b"]
192+
193+
194+
def test_unknown_dependency(item_names_for, order_dependencies, capsys):
195+
tests_content = """
196+
import pytest
197+
198+
class Test:
199+
def test_a(self):
200+
assert True
201+
202+
@pytest.mark.dependency(depends=['test_3'])
203+
def test_b(self):
204+
assert True
205+
206+
def test_c(self):
207+
assert True
208+
"""
209+
assert item_names_for(tests_content) == ["test_a", "test_c", "test_b"]
210+
out, err = capsys.readouterr()
211+
warning = ("cannot execute test relative to others: "
212+
"test_unknown_dependency.Test.test_3 "
213+
"enqueue them behind the others")
214+
assert warning in out

0 commit comments

Comments
 (0)