gpt4 book ai didi

python - FactoryBoy - 嵌套工厂/最大深度?

转载 作者:太空狗 更新时间:2023-10-29 20:31:44 25 4
gpt4 key购买 nike

我正在为一个大型 Django 应用程序编写测试,作为这个过程的一部分,我正在逐渐为 Django 项目中不同应用程序的所有模型创建工厂。

但是,我在 FactoryBoy 中遇到了一些令人困惑的行为,它几乎看起来像 SubFactories。有一个最大深度,超过这个深度就不会生成实例。

当我尝试运行以下测试时出现错误:

    def test_subfactories(self):
""" Verify that the factory is able to initialize """
user = UserFactory()
self.assertTrue(user)
self.assertTrue(user.profile)
self.assertTrue(user.profile.tenant)

order = OrderFactory()
self.assertTrue(order)
self.assertTrue(order.user.profile.tenant)

最后一行将失败 ( AssertionError: None is not true ),通过调试器运行此测试表明 order.user.profile.tenant 确实返回 None而不是预期的 Tenant实例。

这里涉及的工厂/模型比较多,但是布局比较简单。

User (django 默认值)和 Profile模型通过 OneToOneField 链接,它(在遇到一些麻烦之后)由 UserFactory 表示和 ProfileFactory

@factory.django.mute_signals(post_save)
class ProfileFactory(factory.django.DjangoModelFactory):

class Meta:
model = yuza_models.Profile
django_get_or_create = ('user',)

user = factory.SubFactory('yuza.factories.UserFactory')
birth_date = factory.Faker('date_of_birth')
street = factory.Faker('street_name')
house_number = factory.Faker('building_number')
city = factory.Faker('city')
country = factory.Faker('country')
avatar_file = factory.django.ImageField(color='blue')
tenant = factory.SubFactory(TenantFactory)
@factory.django.mute_signals(post_save)
class UserFactory(factory.django.DjangoModelFactory):

class Meta:
model = auth_models.User

username = factory.Sequence(lambda n: "user_%d" % n)
first_name = factory.Faker('first_name')
last_name = factory.Faker('last_name')

email = factory.Faker('email')
is_staff = False
is_superuser = False
is_active = True
last_login = factory.LazyFunction(timezone.now)

@factory.post_generation
def profile(self, create, extracted):
if not create:
return
if extracted is None:
ProfileFactory(user=self)

TenantFactory下面表示为 SubFactoryProfileFactory 上以上。

class TenantFactory(factory.django.DjangoModelFactory):
class Meta:
model = elearning_models.Tenant

name = factory.Faker('company')
slug = factory.LazyAttribute(lambda obj: text.slugify(obj.name))
name_manager = factory.Faker('name')
title_manager = factory.Faker('job')
street = factory.Faker('street_name')
house_number = factory.Faker('building_number')
house_number_addition = factory.Faker('secondary_address')

Order链接到 User , 但它的许多方法调用其 self.user.profile.tenant 的字段

class OrderFactory(factory.DjangoModelFactory):
class Meta:
model = Order

user = factory.SubFactory(UserFactory)
order_date = factory.LazyFunction(timezone.now)
price = factory.LazyFunction(lambda: Decimal(random.uniform(1, 100)))
site_tenant = factory.SubFactory(TenantFactory)
no_tax = fuzzy.FuzzyChoice([True, False])

同样,测试中的大多数断言都没有失败,所有单独的工厂都能够从它们的直接外键关系中初始化获取值。但是,只要工厂/模型彼此相隔三步,调用就会返回 None 而不是预期的 Tenant。实例。

由于我无法在 FactoryBoy 文档中找到任何对此行为的引用,这可能是我这边的错误,但到目前为止我无法确定其来源。有谁知道我做错了什么?

post_save 方法

def create_user_profile(sender, instance, created, **kwargs):
if created:
profile = Profile.objects.create(user=instance)
resume = profile.get_resume()
resume.initialize()


post_save.connect(create_user_profile, sender=User)

最佳答案

正如我在评论中提到的,我发现了问题的根源:链接到 UserProfilepost-save 方法(我已经包含了代码在我的帖子中)。

post-save 方法在 User 创建时创建了一个 Profile。我通过在 UserFactoryProfileFactory 上使用 @factory.django.mute_signals 装饰器来解释这个信号。

我曾假设对 Order.user 的任何调用都会触发已经包含在装饰器中的 UserFactory,但这并不是假设被证明是错误的。只有当我将装饰器也应用到 OrderFactory 时,测试才通过。

因此 @factory.django.mute_signals 装饰器不应该只用在受这些信号影响的工厂上,也应该用在任何将这些工厂用作 SubFactory< 的工厂上!

关于python - FactoryBoy - 嵌套工厂/最大深度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55748322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com