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,所以它可能还有其他问题。这至少应该能帮助您解决一半的问题,如果不能解决另一半的话。