pytest-django icon indicating copy to clipboard operation
pytest-django copied to clipboard

`transactional_db` will ignore `--keep-db` and always flush the db after the test

Open TauPan opened this issue 2 years ago • 2 comments

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).

TauPan avatar Nov 22 '21 11:11 TauPan

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

TauPan avatar Nov 22 '21 13:11 TauPan

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.

westhomas avatar May 05 '23 22:05 westhomas