Pytest 在测试前设置 class 一次
Pytest setup class once before testing
我正在使用 pytest 来测试混合器库以生成模型数据。所以,现在我正在尝试在 运行 之前设置我的测试一次。我将它们分组到 TestClasses 中,设置为我的固定装置 'class' 范围,但这对我不起作用。
@pytest.mark.django_db
class TestCreateTagModel:
@classmethod
@pytest.fixture(autouse=True, scope='class')
def _set_up(cls, create_model_instance, tag_model, create_fake_instance):
cls.model = tag_model
cls.tag = create_model_instance(cls.model)
cls.fake_instance = create_fake_instance(cls.model)
print('setup')
def test_create_tag(self, tag_model, create_model_instance, check_instance_exist):
tag = create_model_instance(tag_model)
assert check_instance_exist(tag_model, tag.id)
conftest.py
pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_model_instance():
instance = None
def wrapper(model, **fields):
nonlocal instance
if not fields:
instance = mixer.blend(model)
else:
instance = mixer.blend(model, **fields)
return instance
yield wrapper
if instance:
instance.delete()
@pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_fake_instance(create_related_fields):
"""
Function for creating fake instance of model(fake means that this instance doesn't exists in DB)
Args:
related (bool, optional): Flag which indicates create related objects or not. Defaults to False.
"""
instance = None
def wrapper(model, related=False, **fields):
with mixer.ctx(commit=False):
instance = mixer.blend(model, **fields)
if related:
create_related_fields(instance, **fields)
return instance
yield wrapper
if instance:
instance.delete()
@pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_related_fields():
django_rel_types = ['ForeignKey']
def wrapper(instance, **fields):
for f in instance._meta.get_fields():
if type(f).__name__ in django_rel_types:
rel_instance = mixer.blend(f.related_model)
setattr(instance, f.name, rel_instance)
return wrapper
但我在 mixer gen_value 方法中捕获异常:不允许访问数据库,使用 django_db 标记(我已经在使用)。您知道如何实施吗?
您可以在 运行 之前设置一次,方法是返回设置结果,而不是直接修改测试 class。从我自己的尝试来看,当个别测试 运行 时,在 class-scope 中对 class 所做的任何更改似乎都会丢失。所以这就是你应该如何做到这一点。用这些替换你的 _setup 装置:
@pytest.fixture(scope='class')
def model_instance(self, tag_model, create_model_instance):
return create_model_instance(tag_model)
@pytest.fixture(scope='class')
def fake_instance(self, tag_model, create_fake_instance):
return create_fake_instance(tag_model)
然后可以通过以下方式访问:
def test_something(self, model_instance, fake_instance):
# Check that model_instance and fake_instance are as expected
虽然我自己并不熟悉 Django,所以它可能还有其他问题。这至少应该能帮助您解决一半的问题,如果不能解决另一半的话。
我正在使用 pytest 来测试混合器库以生成模型数据。所以,现在我正在尝试在 运行 之前设置我的测试一次。我将它们分组到 TestClasses 中,设置为我的固定装置 'class' 范围,但这对我不起作用。
@pytest.mark.django_db
class TestCreateTagModel:
@classmethod
@pytest.fixture(autouse=True, scope='class')
def _set_up(cls, create_model_instance, tag_model, create_fake_instance):
cls.model = tag_model
cls.tag = create_model_instance(cls.model)
cls.fake_instance = create_fake_instance(cls.model)
print('setup')
def test_create_tag(self, tag_model, create_model_instance, check_instance_exist):
tag = create_model_instance(tag_model)
assert check_instance_exist(tag_model, tag.id)
conftest.py
pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_model_instance():
instance = None
def wrapper(model, **fields):
nonlocal instance
if not fields:
instance = mixer.blend(model)
else:
instance = mixer.blend(model, **fields)
return instance
yield wrapper
if instance:
instance.delete()
@pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_fake_instance(create_related_fields):
"""
Function for creating fake instance of model(fake means that this instance doesn't exists in DB)
Args:
related (bool, optional): Flag which indicates create related objects or not. Defaults to False.
"""
instance = None
def wrapper(model, related=False, **fields):
with mixer.ctx(commit=False):
instance = mixer.blend(model, **fields)
if related:
create_related_fields(instance, **fields)
return instance
yield wrapper
if instance:
instance.delete()
@pytest.fixture(scope='class')
@pytest.mark.django_db(transaction=True)
def create_related_fields():
django_rel_types = ['ForeignKey']
def wrapper(instance, **fields):
for f in instance._meta.get_fields():
if type(f).__name__ in django_rel_types:
rel_instance = mixer.blend(f.related_model)
setattr(instance, f.name, rel_instance)
return wrapper
但我在 mixer gen_value 方法中捕获异常:不允许访问数据库,使用 django_db 标记(我已经在使用)。您知道如何实施吗?
您可以在 运行 之前设置一次,方法是返回设置结果,而不是直接修改测试 class。从我自己的尝试来看,当个别测试 运行 时,在 class-scope 中对 class 所做的任何更改似乎都会丢失。所以这就是你应该如何做到这一点。用这些替换你的 _setup 装置:
@pytest.fixture(scope='class')
def model_instance(self, tag_model, create_model_instance):
return create_model_instance(tag_model)
@pytest.fixture(scope='class')
def fake_instance(self, tag_model, create_fake_instance):
return create_fake_instance(tag_model)
然后可以通过以下方式访问:
def test_something(self, model_instance, fake_instance):
# Check that model_instance and fake_instance are as expected
虽然我自己并不熟悉 Django,所以它可能还有其他问题。这至少应该能帮助您解决一半的问题,如果不能解决另一半的话。