diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index d004b3502..09c61c801 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -245,14 +245,14 @@ def pytest_load_initial_conftests(early_config, parser, args): early_config.addinivalue_line( "markers", "django_db(transaction=False): Mark the test as using " - "the django test database. The *transaction* argument marks will " + "the Django test database. The *transaction* argument marks will " "allow you to use real transactions in the test like Django's " "TransactionTestCase.", ) early_config.addinivalue_line( "markers", "urls(modstr): Use a different URLconf for this test, similar to " - "the `urls` attribute of Django `TestCase` objects. *modstr* is " + "the `urls` attribute of Django's `TestCase` objects. *modstr* is " "a string specifying the module of a URL config, e.g. " '"my_app.test_urls".', ) @@ -425,6 +425,30 @@ def pytest_runtest_setup(item): _disable_class_methods(item.cls) +def pytest_collection_modifyitems(session, config, items): + def get_order_number(test): + marker_db = test.get_closest_marker('django_db') + if marker_db: + transaction = validate_django_db(marker_db)[0] + if transaction is True: + return 1 + else: + transaction = None + + fixtures = getattr(test, 'funcargnames', []) + if "transactional_db" in fixtures: + return 1 + + if transaction is False: + return 0 + if "db" in fixtures: + return 0 + + return 2 + + items[:] = sorted(items, key=get_order_number) + + @pytest.fixture(autouse=True, scope="session") def django_test_environment(request): """ diff --git a/tests/test_db_setup.py b/tests/test_db_setup.py index caf4a6ab0..28ee6cf83 100644 --- a/tests/test_db_setup.py +++ b/tests/test_db_setup.py @@ -29,6 +29,38 @@ def test_db_can_be_accessed(): result.stdout.fnmatch_lines(["*test_db_can_be_accessed PASSED*"]) +def test_db_order(django_testdir): + """Test order in which tests are being executed.""" + + django_testdir.create_test_module(''' + import pytest + + from .app.models import Item + + @pytest.mark.django_db(transaction=True) + def test_run_second_decorator(): + pass + + def test_run_second_fixture(transactional_db): + pass + + def test_run_first_fixture(db): + pass + + @pytest.mark.django_db + def test_run_first_decorator(): + pass + ''') + result = django_testdir.runpytest_subprocess('-v', '-s') + assert result.ret == 0 + result.stdout.fnmatch_lines([ + "*test_run_first_fixture*", + "*test_run_first_decorator*", + "*test_run_second_decorator*", + "*test_run_second_fixture*", + ]) + + def test_db_reuse(django_testdir): """ Test the re-use db functionality.