pytest-dev / pytest-django

A Django plugin for pytest.
https://pytest-django.readthedocs.io/
Other
1.37k stars 344 forks source link

database table is locked: auth_user #229

Open bubenkoff opened 9 years ago

bubenkoff commented 9 years ago

When i try to log in to live_server with a browser, i get this:

OperationalError at /login/

database table is locked: auth_user

Request Method:     POST
Request URL:    http://localhost:8081/login/

do we keep transaction opened somewhere?

blueyed commented 9 years ago

This should work like that.

What database are you using? How does your test look like?

bubenkoff commented 9 years ago

sqlite3 backend is used for tests I've read about how it works more and see that it's not realistic to use sqlite3 for functional tests, looks like

bubenkoff commented 9 years ago

ok i now use postgres backend...

my piece of code looks like:

@pytest.fixture
def browser(request, user_role, browser, admin_user, base_url):
    """Pre-log in with given user role."""
    browser.visit(base_url + '/login/')
    browser.fill_form({
        'username': admin_user.username,
        'password': 'password'
    })
    browser.find_by_css('input[type=submit]').click()
    return browser

but the admin_user is still in transaction, so not committed and the live_server can't see the db record of course How do i commit?

from django.db import transaction
transaction.commit()
*** django.db.transaction.TransactionManagementError: This is forbidden when an 'atomic' block is active.

that's because of ATOMIC_REQUESTS = True in my settings i guess

bubenkoff commented 9 years ago

Ok now i see what was wrong:

as db fixture works, it checks if live_server fixture is used or not, but this trick is not documented :) so i didn't know that i should have been requested live_server BEFORE any fixture which uses db fixture

bubenkoff commented 9 years ago

and now it actually works with sqlite3 in memory :)

blueyed commented 9 years ago

(from #230)

db fixture could, and it tries, just it's not easy: it checks if live_server is used, but what if it's used, just LATER than db

Shouldn't all collected/used fixtures be visible to db for the test in question? (request.funcargnames)

if 'transactional_db' in request.funcargnames \
        or 'live_server' in request.funcargnames:
    return request.getfuncargvalue('transactional_db')

Or isn't this provided for earlier fixtures, like in your case?

def browser(request, user_role, browser, admin_user, base_url)

Have you used the live_server fixture with the test using the browser fixture? I think the fix would be to request the live_server fixture with your browser fixture already (or the transactional_db fixture).

The (default) admin_user requests the db fixture, but that is not enough when used with live_server, which needs and should request transactional_db instead.

My browser fixture looks like this:

def browser(browser, request, live_server):
bubenkoff commented 9 years ago

request.funcargnames is filled fixture by fixture (when it's actually called)

bubenkoff commented 9 years ago

the final working variant:

@pytest.fixture
def user_role():
    """User role."""
    return 'superuser'

@pytest.fixture(autouse=True)
def base_url(live_server):
    """Base url."""
    return live_server.url

@pytest.fixture
def browser(base_url, request, user_role, admin_user, browser):
    """Pre-log in with given user role."""
    browser.visit(base_url + '/login/')
    browser.fill_form({
        'username': admin_user.username,
        'password': 'password'
    })
    browser.find_by_css('input[type=submit]').click()
    return browser
blueyed commented 9 years ago

Have you used live_server in your base_url fixture initially already (when reporting the issue)?

Because I still don't see why the browser fixture would not end up using transactional_db (through base_url) - also when using base_url at the end of the argument list. transactional_db should override any db that has been requested before (there might be a bug though).

bubenkoff commented 9 years ago

yes i did used live_server in base_url initially as well

blueyed commented 9 years ago

I consider this to be a bug then. We should have a test that triggers this and then fix it.