pytest-django add fixtures to live_server fixture
Asked Answered
B

2

6

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)
Besse answered 28/9, 2018 at 19:45 Comment(0)
B
0

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)
Besse answered 4/4, 2019 at 16:59 Comment(1)
@Cornellcornelle this is basically what I had to doBesse
A
2

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):
    ...
Apache answered 29/9, 2018 at 17:0 Comment(2)
Yeah I had originally just copied the live_server definition into our code base but didn't particularly like the solution given it would mean we'd have to update the fixture in the event of any changes to the upstream code base. I was hoping there was some way of "passing" fixtures to it via a settings or what not. Ended up with a simple wrapper fixture. Seemed to be the least convoluted solution. Also thanks for the edits.Besse
@Besse Would you mind sharing the simple wrapper fixture you went with?Cornellcornelle
B
0

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)
Besse answered 4/4, 2019 at 16:59 Comment(1)
@Cornellcornelle this is basically what I had to doBesse

© 2022 - 2024 — McMap. All rights reserved.