pytest-django
pytest-django copied to clipboard
`transactional_db` will ignore `--keep-db` and always flush the db after the test
I haven't found this exact issue anywhere, apologies if I missed something.
My special use-case is (ab-)using pytest-django for integration tests on a real server (of course not in production) and I was using the following fixture to prevent database setup and teardown:
@pytest.fixture(scope="session")
def django_db_setup():
return
(With the database being set up for the test in separate code.)
With the normal django_db
and db
markers/fixtures this works and doesn't flush the database. As soon as I add transaction=True
or use transactional_db
the database is always flushed.
The reason the flushing is done is that TransactionTestCase
calls the flush command in its teardown method.
As a workaround I resorted to using the following fixture instead of transactional_db
:
@pytest.fixture(scope="function")
def my_integration_transactional_db(request, django_db_setup,
django_db_blocker):
"""cannibalized from transactional_db fixture
but without the possible customization
- Won't check if we're called from a django testcase
- Won't reset sequences
- Don't care if we're called from a live server (that's handled
from the live_server fixture
)
- And MOST IMPORTANTLY: won't perform teardown (NO FLUSH!)
"""
django_db_blocker.unblock()
request.addfinalizer(django_db_blocker.restore)
from django.test import TransactionTestCase
test_case = TransactionTestCase(methodName="__init__")
test_case._pre_setup()
The most important thing here is that I skip the finalizer altogether (which works in my special use-case if database setup and teardown is done separately).
I'm talking about this teardown: https://github.com/pytest-dev/pytest-django/blob/master/pytest_django/fixtures.py#L186 which will call flush
e.g. here https://github.com/django/django/blob/main/django/test/testcases.py#L1057
I needed some other feature of TransactionTestCase
that I couldn't identify, so I ended up monkey-patching flush to... not flush.
@pytest.fixture(scope="session")
def django_db_setup() -> None:
def _noop(obj, **options):
pass
from django.core.management.commands import flush
flush.Command.handle = _noop
It's ugly, but it fits my need to debug test results in the test database.