Adam
Adam

Reputation: 4172

pytest-django add fixtures to live_server fixture

I need to add fixtures to the live_server fixture provided by pytest-django specifically an overwritten django_db_setup.

That being said I understand it is not ideal to run tests against a db that isn't flushed clean but it is what I am working with.

In our normal test suite we use overwrite the django_db_setup to do nothing in our conftest.py file as follows

@pytest.fixture(scope="session")
def django_db_setup():
    pass

It appears that when I use the live_server fixture provided by pytest-django it does not honor this as it attempts to flush the db at the end of the tests. How would one go about circumventing this? I've found an end around shown below but I'd like to avoid it if there is a better solution.

@pytest.fixture(scope='session')
def my_live_server(request):
    request.getfixturevalue('django_db_setup')
    return live_server(request)

Upvotes: 6

Views: 2278

Answers (2)

Adam
Adam

Reputation: 4172

This is what I had to do to get around it. I am however getting a pytest warning for directly invoking the live_server fixture. This can be avoided pytest<4

@pytest.fixture(scope="session")
def my_live_server(request):
    request.getfixturevalue("fixture_i_want")
    return live_server(request)

Upvotes: 0

hoefling
hoefling

Reputation: 66281

It appears that when I use the live_server fixture provided by pytest-django it does not honor this as it attempts to flush the db at the end of the tests.

You're absolutely right; using the live-server fixture in a test will silently trigger transactional behaviour (as if you would pass transactional_db fixture to the test). AFAIK this can't be turned off via configuration (I will be glad if proven wrong); one has to mess with pytest-django's internals. In your conftest.py:

# conftest.py

import pytest

@pytest.fixture(scope="session")
def django_db_setup():
    pass

@pytest.fixture(autouse=True, scope='function')
def _live_server_helper(request):
    if 'live_server' not in request.funcargnames:
        return

    request.getfixturevalue('django_db_setup')

    live_server = request.getfixturevalue('live_server')
    live_server._live_server_modified_settings.enable()
    request.addfinalizer(live_server._live_server_modified_settings.disable)

Sure, it's not a nice solution, but it does the trick. You can at least "mitigate the possible damage" by introducing a custom marker so that the patched helper is only applied to marked tests:

@pytest.fixture(autouse=True, scope='function')
def _live_server_helper(request):
    markers = [marker.name for marker in request.node.iter_markers()]
    if 'live_server_no_flush' not in markers:
        request.getfixturevalue('_live_server_helper')
        return

    # rest of code same as above
    if 'live_server' not in request.funcargnames:
        return

    request.getfixturevalue('django_db_setup')

    live_server = request.getfixturevalue('live_server')
    live_server._live_server_modified_settings.enable()
    request.addfinalizer(live_server._live_server_modified_settings.disable)

Now the new behaviour is applied only to tests marked with live_server_no_flush:

@pytest.mark.live_server_no_flush
def test_spam(live_server):
    ...

Upvotes: 2

Related Questions