Skip to content

Commit 78c73c4

Browse files
committed
Run tests in the same order as Django
This uses `pytest_collection_modifyitems` to order the tests. Fixes #214.
1 parent 4d61618 commit 78c73c4

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

pytest_django/plugin.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,13 @@ def pytest_load_initial_conftests(early_config, parser, args):
176176
early_config.addinivalue_line(
177177
'markers',
178178
'django_db(transaction=False): Mark the test as using '
179-
'the django test database. The *transaction* argument marks will '
180-
"allow you to use real transactions in the test like Django's "
179+
'the Django test database. The *transaction* argument '
180+
"allows you to use real transactions in the test like with Django's "
181181
'TransactionTestCase.')
182182
early_config.addinivalue_line(
183183
'markers',
184184
'urls(modstr): Use a different URLconf for this test, similar to '
185-
'the `urls` attribute of Django `TestCase` objects. *modstr* is '
185+
"the `urls` attribute of Django's `TestCase` objects. *modstr* is "
186186
'a string specifying the module of a URL config, e.g. '
187187
'"my_app.test_urls".')
188188
early_config.addinivalue_line(
@@ -339,6 +339,34 @@ def pytest_runtest_setup(item):
339339
_disable_class_methods(cls)
340340

341341

342+
def pytest_collection_modifyitems(session, config, items):
343+
def get_marker_transaction(test):
344+
marker = test.get_marker("django_db")
345+
if marker:
346+
validate_django_db(marker)
347+
return marker.transaction
348+
return None
349+
350+
def has_fixture(test, fixture):
351+
funcargnames = getattr(test, 'funcargnames', None)
352+
return funcargnames and fixture in funcargnames
353+
354+
def get_order_number(test):
355+
if get_marker_transaction(test) is True:
356+
return 1
357+
if has_fixture(test, 'transactional_db'):
358+
return 1
359+
360+
if get_marker_transaction(test) is False:
361+
return 0
362+
if has_fixture(test, 'db'):
363+
return 0
364+
365+
return 2
366+
367+
items[:] = sorted(items, key=get_order_number)
368+
369+
342370
@pytest.fixture(autouse=True, scope='session')
343371
def django_test_environment(request):
344372
"""

tests/test_db_setup.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,38 @@ def test_db_can_be_accessed():
2525
])
2626

2727

28+
def test_db_order(django_testdir):
29+
"""Test order in which tests are being executed."""
30+
31+
django_testdir.create_test_module('''
32+
import pytest
33+
34+
from .app.models import Item
35+
36+
@pytest.mark.django_db(transaction=True)
37+
def test_run_second_decorator():
38+
pass
39+
40+
def test_run_second_fixture(transactional_db):
41+
pass
42+
43+
def test_run_first_fixture(db):
44+
pass
45+
46+
@pytest.mark.django_db
47+
def test_run_first_decorator():
48+
pass
49+
''')
50+
result = django_testdir.runpytest_subprocess('-v', '-s')
51+
assert result.ret == 0
52+
result.stdout.fnmatch_lines([
53+
"*test_run_first_fixture*",
54+
"*test_run_first_decorator*",
55+
"*test_run_second_decorator*",
56+
"*test_run_second_fixture*",
57+
])
58+
59+
2860
def test_db_reuse(django_testdir):
2961
"""
3062
Test the re-use db functionality.

0 commit comments

Comments
 (0)