Skip to content

Commit d7d89c7

Browse files
committed
Run tests in the same order as Django
This uses `pytest_collection_modifyitems` to order the tests. Fixes #214.
1 parent 5d6a7ef commit d7d89c7

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

pytest_django/plugin.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,14 @@ def pytest_load_initial_conftests(early_config, parser, args):
245245
early_config.addinivalue_line(
246246
"markers",
247247
"django_db(transaction=False): Mark the test as using "
248-
"the django test database. The *transaction* argument marks will "
248+
"the Django test database. The *transaction* argument marks will "
249249
"allow you to use real transactions in the test like Django's "
250250
"TransactionTestCase.",
251251
)
252252
early_config.addinivalue_line(
253253
"markers",
254254
"urls(modstr): Use a different URLconf for this test, similar to "
255-
"the `urls` attribute of Django `TestCase` objects. *modstr* is "
255+
"the `urls` attribute of Django's `TestCase` objects. *modstr* is "
256256
"a string specifying the module of a URL config, e.g. "
257257
'"my_app.test_urls".',
258258
)
@@ -425,6 +425,32 @@ def pytest_runtest_setup(item):
425425
_disable_class_methods(item.cls)
426426

427427

428+
def pytest_collection_modifyitems(session, config, items):
429+
def get_marker_transaction(test):
430+
marker = test.get_closest_marker('django_db')
431+
if marker:
432+
return validate_django_db(marker)[0]
433+
return None
434+
435+
def has_fixture(test, fixture):
436+
return fixture in getattr(test, 'funcargnames', [])
437+
438+
def get_order_number(test):
439+
if get_marker_transaction(test) is True:
440+
return 1
441+
if has_fixture(test, "transactional_db"):
442+
return 1
443+
444+
if get_marker_transaction(test) is False:
445+
return 0
446+
if has_fixture(test, "db"):
447+
return 0
448+
449+
return 2
450+
451+
items[:] = sorted(items, key=get_order_number)
452+
453+
428454
@pytest.fixture(autouse=True, scope="session")
429455
def django_test_environment(request):
430456
"""

tests/test_db_setup.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,38 @@ def test_db_can_be_accessed():
2929
result.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"])
3030

3131

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

0 commit comments

Comments
 (0)