如何在pytest中向FactoryBoy嵌套RelatedFactories传递参数?
解决FactoryBoy多层关联工厂的参数传递问题
完全可以实现你的需求,用FactoryBoy的Class Params作为状态载体是合理方案,适配你这种多层关联、多依赖工厂的场景。下面是具体实现方式:
修改后的工厂代码
import factory from .models import FruitBasket, Apple, Seed, Skin class FruitBasketFactory(factory.django.DjangoModelFactory): class Meta: model = FruitBasket # 定义顶层控制参数,默认关闭PinkLady类型 class Params: apple_type_is_PinkLady = False # 将顶层参数传递给AppleFactory apple = factory.RelatedFactory( "your_app.factories.AppleFactory", factory_related_name="fruit_basket", apple_type_is_PinkLady=factory.SelfAttribute("..apple_type_is_PinkLady"), ) class AppleFactory(factory.django.DjangoModelFactory): class Meta: model = Apple fruit_basket = None # 接收上层传递的参数 class Params: apple_type_is_PinkLady = False # 将参数传递给SeedFactory和SkinFactory seed = factory.RelatedFactory( "your_app.factories.SeedFactory", factory_related_name="apple", apple_type_is_PinkLady=factory.SelfAttribute("..apple_type_is_PinkLady"), ) skin = factory.RelatedFactory( "your_app.factories.SkinFactory", factory_related_name="apple", apple_type_is_PinkLady=factory.SelfAttribute("..apple_type_is_PinkLady"), ) class SeedFactory(factory.django.DjangoModelFactory): class Meta: model = Seed apple = None # 接收参数并设置默认属性 class Params: apple_type_is_PinkLady = False # 根据参数动态覆盖属性值 num_seeds = factory.Maybe( "apple_type_is_PinkLady", yes=5, no=10, ) seed_color = factory.Maybe( "apple_type_is_PinkLady", yes="brown", no="black", ) class SkinFactory(factory.django.DjangoModelFactory): class Meta: model = Skin apple = None class Params: apple_type_is_PinkLady = False skin_color = factory.Maybe( "apple_type_is_PinkLady", yes="green", no="red", )
关键实现细节
- 参数传递链路:通过
factory.SelfAttribute("..apple_type_is_PinkLady")实现跨层级参数传递,..表示向上访问父级工厂的属性。 - 动态属性覆盖:使用
factory.Maybe根据参数值切换属性默认值,逻辑清晰且易于扩展。 - 扩展性:如果中间工厂有5-10个关联工厂,只需在中间工厂的每个
RelatedFactory中传递该参数,子工厂按需添加Params和Maybe逻辑即可,不会产生冗余代码。
使用方式
在测试中直接调用顶层工厂并传入参数:
# 创建普通果篮 normal_basket = FruitBasketFactory() assert normal_basket.apple.seed.num_seeds == 10 assert normal_basket.apple.seed.seed_color == "black" assert normal_basket.apple.skin.skin_color == "red" # 创建PinkLady类型的果篮 pink_lady_basket = FruitBasketFactory(apple_type_is_PinkLady=True) assert pink_lady_basket.apple.seed.num_seeds == 5 assert pink_lady_basket.apple.seed.seed_color == "brown" assert pink_lady_basket.apple.skin.skin_color == "green"
内容的提问来源于stack exchange,提问作者chillingfox
相关产品推荐
相关产品推荐

