I have the following inside conftest.py
@pytest.mark.django_db
@pytest.fixture(scope='module')
def thing():
print('sleeping') # represents a very expensive function that i want to only ever once once per module
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
Inside tests.py
@pytest.mark.django_db
def test_thing(thing):
assert models.Thing.objects.count() > 1
@pytest.mark.django_db
def test_thing2(thing):
assert models.Thing.objects.count() > 1
@pytest.mark.django_db
@pytest.mark.usefixtures('thing')
def test_thing3():
assert models.Thing.objects.count() > 1
All three tests throw the same error: RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
I've tried using scope='session'
/ scope='class'
/ scope='package'
/ scope='module'
-- the only one that works is `scope='function' which defeats the purpose of what I'm trying to accomplish. I want to be able to create all these items ONCE per module, not once per test.
Note: I ran into this issue with a large code base and created a new django project with a single app to test and see if the problem was the existing test code, and it failed on a standalone test also. Tested it with both postgres and sqlite; doesn't seem like a database issue.
Not that it matters, but the models.py
class Thing(models.Model):
thing = models.CharField(max_length=100)
CodePudding user response:
You can request db
fixture in fixture instead. It is described in docs in first note.
If you want access to the Django database inside a fixture, this marker may or may not help even if the function requesting your fixture has this marker applied, depending on pytest’s fixture execution order. To access the database in a fixture, it is recommended that the fixture explicitly request one of the db, transactional_db, django_db_reset_sequences or django_db_serialized_rollback fixtures. (emphasis mine)
# conftest.py
@pytest.fixture(scope='module')
def thing(db): # Use "db" fixture
print('sleeping') # represents a very expensive function that i want to only ever once once per module
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
CodePudding user response:
Ok, turns out this is a known limitation, and it's somewhat documented here. If you want to solve this issue, and get away from this bug:
@pytest.mark.django_db
@pytest.fixture(scope='module')
def thing(django_db_setup, django_db_blocker):
del django_db_setup # Cannot be used with usefixtures(..) it won't work
with django_db_blocker.unblock():
print('sleeping')
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
Thing.objects.create(thing='hello')
yield