The live_server fixture is session-scoped while the transactional_db fixture (which live_server implicitly enables) is function-scoped.
As a consequence, live_server can handle requests during the whole duration of the test suite. These requests can collide with the database flushes that transactional_db performs after each test or with the periods when access to the database is disabled between two tests.
Here's what the sequence of events looks like:
live_server fixture starts a LiveServerThreadtransactional_db fixture runs (triggered by the function-scoped, autouse _live_server_helper fixture) and adds TransactionTestCase._post_teardown to finalizerstransactional_db finalizer runs and attempts to flush the database, conflicting with the requests the live server is still processinglive_server finalizer waits for LiveServerThread to terminateThe conflict can cause deadlocks between any SQL query from a HTTP request handled by the live server and the query that flushes the database, which looks like this:
Exception Database test_xxxxxxxx couldn't be flushed. Possible reasons:
* The database isn't running or isn't configured correctly.
* At least one of the expected database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin sqlflush'. That's the SQL this command wasn't able to run.
The full error: deadlock detected
DETAIL: Process 37253 waits for AccessExclusiveLock on relation 131803 of database 131722; blocked by process 37250.
Process 37250 waits for AccessShareLock on relation 132659 of database 131722; blocked by process 37253.
HINT: See server log for query details.
This failure mode is particularly annoying because the database isn't flushed, requiring to next test run to re-create the database and thus negating the benefits of --reuse-db.
If database reuse isn't enabled, destroying the test database can fail with:
django.db.utils.OperationalError: database "test_xxxxxxxx" is being accessed by other users
DETAIL: There is 1 other session using the database.
I've also seen SQL queries from HTTP requests handled by the live server to fail with:
Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
because the transactional_db finalizer has flushed the database and blocked access until the next test.
I'm planning to look for workarounds and will update this ticket with my findings.
Running into this as well. Did you find anything?
Nope.
I'll report my findings here if I find time to work on a solution. It isn't near the top of my TODO list.
I'm having the same(?) problem, live_server fixture does not see changes made to the database, running in it's own transaction. @aaugustin , does it sound likely to you?
I was wondering... maybe I should ditch the live_server fixture totally and just write my replacement. It would consist of running "manage.py runserver" in a thread. Except pointing it to a test database, I'd not update project settings. At some point I may need that. Also, LiveServerTestCase does not support custom STATICFILES_FINDERS except the filesystem one...
I'm also running into this issue. Current workaround I'm using is to override the live_server fixture so that it is function scoped. Specifically, my conftest.py file contains the following:
from pytest_django.fixtures import live_server as orig_live_server
@pytest.fixture(scope='function')
def live_server(request):
"""
Workaround inspired by https://github.com/mozilla/addons-server/pull/4875/files#diff-0223c02758be2ac7967ea22c6fa4b361R96
"""
return orig_live_server(request)
This seems like it's working, though admittedly, it slows all the test cases that use it _way_ down. If anyone sees a problem with this approach, please let me know.
I have similar problem: live_server is not working, it prints error no such table: django_session.
The @Helumpago's workaround fixed this error for me. But pytest prints this warning:
RemovedInPytest4Warning: Fixture "live_server" called directly. Fixtures are not meant to be called directly, are created automatically when test functions request them as parameters.
Is there any other way to use live_server with a database?
The @Helumpago's workaround raises an error instead of warning since pytest 4.0 (2018-11-13) :(
UPD: looks like it works (but this is ugly)
from pytest_django.fixtures import live_server as orig_live_server
live_server = pytest.fixture(scope='function')(orig_live_server.__wrapped__)
I have had some success with the code below, but (YMMV)
@pytest.fixture(name='live_server', scope='function')
def _live_server(live_server):
# This rescopes the live_server fixture to function scope
# See https://github.com/pytest-dev/pytest-django/issues/454
return live_server
scope='function' is not technically required as the default scope is function but is added for clarity
I'm running into this too. No doubt all the above variants of the fix will work.
But I'm wondering: what is the correct behavior here? It seems like, the root problem is actually those AJAX requests still happening after the test finishes. Rightly so, they should prevent the database from flushing.
Think about it in real life and not a test. If you had a DB and wanted to run a flush command, and had a ton of active requests towards that table, wouldn't you expect an error or to have to handle it, rather than it just working and magically killing all those pending requests?
I can think of a few options:
psql postgres -c 'SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid <> EVERYTHING_BUT_PYTEST_PID';
Most helpful comment
I have had some success with the code below, but (YMMV)
scope='function'is not technically required as the default scope isfunctionbut is added for clarity