Skip to content

Commit 76b10f1

Browse files
committed
Run tests in the same order as Django
This uses `pytest_collection_modifyitems` to order the tests. Fixes #214.
1 parent b8bdd8e commit 76b10f1

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
@@ -189,13 +189,13 @@ def pytest_load_initial_conftests(early_config, parser, args):
189189
early_config.addinivalue_line(
190190
'markers',
191191
'django_db(transaction=False): Mark the test as using '
192-
'the django test database. The *transaction* argument marks will '
193-
"allow you to use real transactions in the test like Django's "
192+
'the Django test database. The *transaction* argument '
193+
"allows you to use real transactions in the test like with Django's "
194194
'TransactionTestCase.')
195195
early_config.addinivalue_line(
196196
'markers',
197197
'urls(modstr): Use a different URLconf for this test, similar to '
198-
'the `urls` attribute of Django `TestCase` objects. *modstr* is '
198+
"the `urls` attribute of Django's `TestCase` objects. *modstr* is "
199199
'a string specifying the module of a URL config, e.g. '
200200
'"my_app.test_urls".')
201201
early_config.addinivalue_line(
@@ -352,6 +352,34 @@ def pytest_runtest_setup(item):
352352
_disable_class_methods(cls)
353353

354354

355+
def pytest_collection_modifyitems(session, config, items):
356+
def get_marker_transaction(test):
357+
marker = test.get_marker("django_db")
358+
if marker:
359+
validate_django_db(marker)
360+
return marker.transaction
361+
return None
362+
363+
def has_fixture(test, fixture):
364+
funcargnames = getattr(test, 'funcargnames', None)
365+
return funcargnames and fixture in funcargnames
366+
367+
def get_order_number(test):
368+
if get_marker_transaction(test) is True:
369+
return 1
370+
if has_fixture(test, 'transactional_db'):
371+
return 1
372+
373+
if get_marker_transaction(test) is False:
374+
return 0
375+
if has_fixture(test, 'db'):
376+
return 0
377+
378+
return 2
379+
380+
items[:] = sorted(items, key=get_order_number)
381+
382+
355383
@pytest.fixture(autouse=True, scope='session')
356384
def django_test_environment(request):
357385
"""

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)