Skip to content

Commit

Permalink
WIP: Add support for sharing DB data across across a scope
Browse files Browse the repository at this point in the history
  • Loading branch information
bluetech committed Nov 30, 2021
1 parent 80cacd9 commit fcf5ef4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
7 changes: 7 additions & 0 deletions pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,13 @@ def django_db_reset_sequences(
# is requested.


@pytest.fixture(scope='session')
def django_test_data() -> None:
"""A fixture that may be requested by other fixtures to allow
them to modify the database, with all database modifications
rolled back at the end of the scope."""


@pytest.fixture()
def client() -> "django.test.client.Client":
"""A Django test client instance."""
Expand Down
36 changes: 36 additions & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from .fixtures import django_db_use_migrations # noqa
from .fixtures import django_user_model # noqa
from .fixtures import django_username_field # noqa
from .fixtures import django_test_data # noqa
from .fixtures import live_server # noqa
from .fixtures import rf # noqa
from .fixtures import settings # noqa
Expand Down Expand Up @@ -740,3 +741,38 @@ def apifun(urls: List[str]) -> List[str]:
return urls

return apifun(*marker.args, **marker.kwargs)


@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(fixturedef, request):
# Implement the magic of `django_test_data`.
# When a user fixture *directly* requests `django_test_data`,
# its body is wrapped in an atomic block, which is rolled back
# at the end of the fixture's scope (*not* the fixture itself!).

if 'django_test_data' not in fixturedef.argnames:
yield
return

from django.db import transaction

atomics = {}
# TODO
databases = ('default',)
django_db_blocker = request.getfixturevalue('django_db_blocker')

with django_db_blocker.unblock():
for db_name in databases:
atomic = transaction.atomic(using=db_name)
atomic._from_testcase = True
atomic.__enter__()
atomics[db_name] = atomic

yield

def finalize_django_test_data():
with django_db_blocker.unblock():
for db_name in reversed(databases):
transaction.set_rollback(True, using=db_name)
atomics[db_name].__exit__(None, None, None)
request.node.addfinalizer(finalize_django_test_data)

0 comments on commit fcf5ef4

Please sign in to comment.