Skip to content

Commit fcf5ef4

Browse files
committed
WIP: Add support for sharing DB data across across a scope
1 parent 80cacd9 commit fcf5ef4

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

pytest_django/fixtures.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,13 @@ def django_db_reset_sequences(
329329
# is requested.
330330

331331

332+
@pytest.fixture(scope='session')
333+
def django_test_data() -> None:
334+
"""A fixture that may be requested by other fixtures to allow
335+
them to modify the database, with all database modifications
336+
rolled back at the end of the scope."""
337+
338+
332339
@pytest.fixture()
333340
def client() -> "django.test.client.Client":
334341
"""A Django test client instance."""

pytest_django/plugin.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from .fixtures import django_db_use_migrations # noqa
3838
from .fixtures import django_user_model # noqa
3939
from .fixtures import django_username_field # noqa
40+
from .fixtures import django_test_data # noqa
4041
from .fixtures import live_server # noqa
4142
from .fixtures import rf # noqa
4243
from .fixtures import settings # noqa
@@ -740,3 +741,38 @@ def apifun(urls: List[str]) -> List[str]:
740741
return urls
741742

742743
return apifun(*marker.args, **marker.kwargs)
744+
745+
746+
@pytest.hookimpl(hookwrapper=True)
747+
def pytest_fixture_setup(fixturedef, request):
748+
# Implement the magic of `django_test_data`.
749+
# When a user fixture *directly* requests `django_test_data`,
750+
# its body is wrapped in an atomic block, which is rolled back
751+
# at the end of the fixture's scope (*not* the fixture itself!).
752+
753+
if 'django_test_data' not in fixturedef.argnames:
754+
yield
755+
return
756+
757+
from django.db import transaction
758+
759+
atomics = {}
760+
# TODO
761+
databases = ('default',)
762+
django_db_blocker = request.getfixturevalue('django_db_blocker')
763+
764+
with django_db_blocker.unblock():
765+
for db_name in databases:
766+
atomic = transaction.atomic(using=db_name)
767+
atomic._from_testcase = True
768+
atomic.__enter__()
769+
atomics[db_name] = atomic
770+
771+
yield
772+
773+
def finalize_django_test_data():
774+
with django_db_blocker.unblock():
775+
for db_name in reversed(databases):
776+
transaction.set_rollback(True, using=db_name)
777+
atomics[db_name].__exit__(None, None, None)
778+
request.node.addfinalizer(finalize_django_test_data)

0 commit comments

Comments
 (0)