Skip to content

Commit f6a1c9c

Browse files
committed
First hack.
1 parent c6d9153 commit f6a1c9c

File tree

10 files changed

+385
-0
lines changed

10 files changed

+385
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ lib
1919
lib64
2020
__pycache__
2121

22+
# Virtualenvs
23+
env
24+
2225
# Installer logs
2326
pip-log.txt
2427

pytest_ordering.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import re
2+
3+
replacements = {
4+
'first': 0,
5+
'second': 1,
6+
'third': 2,
7+
'fourth': 3,
8+
'fifth': 4,
9+
'sixth': 5,
10+
'seventh': 6,
11+
'eighth': 7,
12+
'last': -1,
13+
'second_to_last': -2,
14+
'third_to_last': -3,
15+
'fourth_to_last': -4,
16+
'fifth_to_last': -5,
17+
'sixth_to_last': -6,
18+
'seventh_to_last': -7,
19+
'eighth_to_last': -8,
20+
}
21+
22+
def pytest_collection_modifyitems(session, config, items):
23+
items[:] = list(_order_tests(items))
24+
25+
26+
def orderable(marker):
27+
match = re.match('^order(\d+)$', marker)
28+
return bool(match) or marker in replacements
29+
30+
31+
def get_index(marker):
32+
match = re.match('^order(\d+)$', marker)
33+
if match:
34+
return int(match.group(1)) - 1
35+
return replacements[marker]
36+
37+
38+
def split(dictionary):
39+
from_beginning, from_end = {}, {}
40+
for key, val in dictionary.items():
41+
if key >= 0:
42+
from_beginning[key] = val
43+
else:
44+
from_end[key] = val
45+
return from_beginning, from_end
46+
47+
48+
def _order_tests(tests):
49+
ordered_tests = {}
50+
remaining_tests = []
51+
for test in tests:
52+
# There has got to be an API for this. :-/
53+
markers = test.keywords.__dict__['_markers']
54+
orderable_markers = [m for m in markers if orderable(m)]
55+
if len(orderable_markers) == 1:
56+
[orderable_marker] = orderable_markers
57+
ordered_tests[get_index(orderable_marker)] = test
58+
else:
59+
remaining_tests.append(test)
60+
from_beginning, from_end = split(ordered_tests)
61+
remaining_iter = iter(remaining_tests)
62+
for i in range(max(from_beginning or [-1]) + 1):
63+
if i in from_beginning:
64+
yield from_beginning[i]
65+
else:
66+
yield next(remaining_iter)
67+
# TODO TODO TODO
68+
for i in range(min(from_end or [0]), 0):
69+
if i in from_end:
70+
yield from_end[i]
71+
else:
72+
yield next(remaining_iter)
73+
for test in remaining_iter:
74+
yield test

setup.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env python
2+
3+
from setuptools import setup
4+
5+
6+
setup(
7+
name='pytest-ordering',
8+
description='pytest plugin to run your tests in a specific order',
9+
version='0.1',
10+
author='Frank Tobia',
11+
author_email='[email protected]',
12+
url='https://github.com/ftobia/pytest-ordering',
13+
packages=['pytest_ordering'],
14+
)

tests/__init__.py

Whitespace-only changes.

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from pytest_ordering import pytest_collection_modifyitems

tests/grouping.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import pytest
2+
3+
ordering = 'ckheofdvgwzyrulmbiqpjnxsta'
4+
5+
6+
@pytest.mark.foo(order=25)
7+
def test_a():
8+
pass
9+
10+
11+
@pytest.mark.foo(order=16)
12+
def test_b():
13+
pass
14+
15+
16+
@pytest.mark.foo(order=0)
17+
def test_c():
18+
pass
19+
20+
21+
@pytest.mark.foo(order=6)
22+
def test_d():
23+
pass
24+
25+
26+
@pytest.mark.foo(order=3)
27+
def test_e():
28+
pass
29+
30+
31+
@pytest.mark.foo(order=5)
32+
def test_f():
33+
pass
34+
35+
36+
@pytest.mark.foo(order=8)
37+
def test_g():
38+
pass
39+
40+
41+
@pytest.mark.foo(order=2)
42+
def test_h():
43+
pass
44+
45+
46+
@pytest.mark.foo(order=17)
47+
def test_i():
48+
pass
49+
50+
51+
@pytest.mark.foo(order=20)
52+
def test_j():
53+
pass
54+
55+
56+
@pytest.mark.foo(order=1)
57+
def test_k():
58+
pass
59+
60+
61+
@pytest.mark.foo(order=14)
62+
def test_l():
63+
pass
64+
65+
66+
@pytest.mark.foo(order=15)
67+
def test_m():
68+
pass
69+
70+
71+
@pytest.mark.foo(order=21)
72+
def test_n():
73+
pass
74+
75+
76+
@pytest.mark.foo(order=4)
77+
def test_o():
78+
pass
79+
80+
81+
@pytest.mark.foo(order=19)
82+
def test_p():
83+
pass
84+
85+
86+
@pytest.mark.foo(order=18)
87+
def test_q():
88+
pass
89+
90+
91+
@pytest.mark.foo(order=12)
92+
def test_r():
93+
pass
94+
95+
96+
@pytest.mark.foo(order=23)
97+
def test_s():
98+
pass
99+
100+
101+
@pytest.mark.foo(order=24)
102+
def test_t():
103+
pass
104+
105+
106+
@pytest.mark.foo(order=13)
107+
def test_u():
108+
pass
109+
110+
111+
@pytest.mark.foo(order=7)
112+
def test_v():
113+
pass
114+
115+
116+
@pytest.mark.foo(order=9)
117+
def test_w():
118+
pass
119+
120+
121+
@pytest.mark.foo(order=22)
122+
def test_x():
123+
pass
124+
125+
126+
@pytest.mark.foo(order=11)
127+
def test_y():
128+
pass
129+
130+
131+
@pytest.mark.foo(order=10)
132+
def test_z():
133+
pass

tests/numbers.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
3+
ordering = 'fcbaged'
4+
5+
6+
@pytest.mark.order4
7+
def test_a():
8+
pass
9+
10+
11+
@pytest.mark.order3
12+
def test_b():
13+
pass
14+
15+
16+
@pytest.mark.order2
17+
def test_c():
18+
pass
19+
20+
21+
@pytest.mark.order7
22+
def test_d():
23+
pass
24+
25+
26+
@pytest.mark.order6
27+
def test_e():
28+
pass
29+
30+
31+
@pytest.mark.order1
32+
def test_f():
33+
pass
34+
35+
36+
@pytest.mark.order5
37+
def test_g():
38+
pass

tests/test_ordering.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import operator
2+
import os
3+
import random
4+
import re
5+
6+
import pytest
7+
8+
from pytest_ordering import _order_tests
9+
10+
__here__ = os.path.dirname(os.path.abspath(__file__))
11+
12+
13+
def get_module(module_name):
14+
return __import__(module_name, globals(), locals(), [], -1)
15+
16+
17+
def get_tests(module_name):
18+
module = get_module(module_name)
19+
return [getattr(module, t) for t in dir(module) if t.startswith('test_')]
20+
21+
22+
def _names_of_tests(output, test_file_name):
23+
regex = r'^{}:(\d+): test_([a-z]) PASSED$'.format(
24+
test_file_name.replace('.', '\.'))
25+
for line in output.split('\n'):
26+
match = re.match(regex, line)
27+
if match:
28+
yield match.group(2)
29+
30+
31+
def get_order(output, test_file_name):
32+
return list(_names_of_tests(output, test_file_name))
33+
34+
35+
# Default sorting is whatever order the tests show up in the module.
36+
37+
@pytest.mark.parametrize('module_name', [
38+
'numbers', 'words', 'words_backwards',
39+
# 'grouping', # This one is going to be tricky.
40+
])
41+
def test_ordering(module_name, capsys):
42+
module = get_module(module_name)
43+
pytest.main('{}/{}.py -vv'.format(__here__, module_name))
44+
relative_filename = 'tests/{}.py'.format(module_name)
45+
out, err = capsys.readouterr()
46+
assert list(module.ordering) == get_order(out, relative_filename)

tests/words.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
3+
ordering = 'dabgfce'
4+
5+
6+
@pytest.mark.second
7+
def test_a():
8+
pass
9+
10+
11+
@pytest.mark.third
12+
def test_b():
13+
pass
14+
15+
16+
@pytest.mark.sixth
17+
def test_c():
18+
pass
19+
20+
21+
@pytest.mark.first
22+
def test_d():
23+
pass
24+
25+
26+
@pytest.mark.seventh
27+
def test_e():
28+
pass
29+
30+
31+
@pytest.mark.fifth
32+
def test_f():
33+
pass
34+
35+
36+
@pytest.mark.fourth
37+
def test_g():
38+
pass

tests/words_backwards.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
3+
ordering = 'dgfbcae'
4+
5+
6+
@pytest.mark.second_to_last
7+
def test_a():
8+
pass
9+
10+
11+
@pytest.mark.fourth_to_last
12+
def test_b():
13+
pass
14+
15+
16+
@pytest.mark.third_to_last
17+
def test_c():
18+
pass
19+
20+
21+
@pytest.mark.seventh_to_last
22+
def test_d():
23+
pass
24+
25+
26+
@pytest.mark.last
27+
def test_e():
28+
pass
29+
30+
31+
@pytest.mark.fifth_to_last
32+
def test_f():
33+
pass
34+
35+
36+
@pytest.mark.sixth_to_last
37+
def test_g():
38+
pass

0 commit comments

Comments
 (0)