这个
db
固定装置有
function
作用域是有原因的,因此每个测试结束时的事务回滚确保数据库保持在测试开始时的相同状态。不过,您可以使用
django_db_blocker
固定装置:
@pytest.fixture(scope='module')
def get_all_models(django_db_blocker):
with django_db_blocker.unblock():
return MyModel.objects.all()
警告
请注意,在会话范围内解锁数据库时,如果在其他fixture或测试中更改数据库,则需要自己完成。在下面的示例中,我创建了
Foo
在会话范围的fixture中
create_foo
,然后在中缓存会话的queryset
all_foos
:
# models.py
from django.db import models
class Foo(models.Model):
name = models.CharField(max_length=16)
# test_foo.py
import pytest
from app.models import Foo
@pytest.fixture(scope='session', autouse=True)
def create_foo(django_db_blocker):
with django_db_blocker.unblock():
Foo.objects.create(name='bar')
@pytest.fixture(scope='module')
def all_foos(django_db_blocker):
with django_db_blocker.unblock():
yield Foo.objects.all()
def test_1(all_foos):
assert all_foos.exists()
def test_2(all_foos, db):
all_foos.delete()
assert not Foo.objects.exists()
def test3(all_foos):
assert all_foos.exists()
之后
test_2
运行,存储在会话中的queryset
所有人
将为空,导致
test_3
失败:
test_foo.py::test_1 PASSED [ 33%]
test_foo.py::test_2 PASSED [ 66%]
test_foo.py::test_3 FAILED [100%]
========================================= FAILURES ========================================
__________________________________________ test_3 _________________________________________
all_foos = <QuerySet []>
def test_3(all_foos):
> assert all_foos.exists()
E assert False
E + where False = <bound method QuerySet.exists of <QuerySet []>>()
E + where <bound method QuerySet.exists of <QuerySet []>> = <QuerySet []>.exists
test_foo.py:28: AssertionError
结果:如果不想引入可以在测试中更改的全局状态,请不要在会话范围中存储引用。从数据库查询数据并返回副本或序列化数据,等等。
安全使用示例:
@pytest.fixture(scope='session')
def foo_names(django_db_blocker):
with django_db_blocker.unblock():
names = list(Foo.objects.values_list('name', flat=True))
return names