Passing kwargs into FactoryBoy nested RelatedFactories for pytest

79 Views Asked by At

I see so many different ways of doing this that I'm getting a bit of choice paralysis.

Problem description

I have a top-level FactoryBoy factory, FruitBasketFactory. This defines a RelatedFactory to AppleFactory, a sort of "conduit" factory: AppleFactory defines 2 RelatedFactories: SeedFactory and SkinFactory. Some pseudo code:

class FruitBasketFactory(factory.django.DjangoModelFactory):
    
    class Meta:
        model = FruitBasket 

    apple = factory.RelatedFactory(
        AppleFactory,
        factory_related_name="fruit_basket"
    )
class AppleFactory(factory.django.DjangoModelFactory):
    
    class Meta:
        model = Apple 
    
    fruit_basket = None
    
    seed = factory.RelatedFactory(
        SeedFactory,
        factory_related_name="apple"
    )
    skin = factory.RelatedFactory(
        SkinFactory,
        factory_related_name="apple"
    )

class SeedFactory(factory.django.DjangoModelFactory):
    
    class Meta:
        model = Seed 
    
    apple = None
    
    num_seeds = 10
    seed_color = "black"

class SkinFactory(factory.django.DjangoModelFactory):
    
    class Meta:
        model = Skin 
    
    apple = None
    
    skin_color="red"

My goal

For my tests, I want to set a top-level flag e.g. fruit_basket_factory(apple_type_is_PinkLady=True), and 'pass down state' to all related, dependent factories. In this case, the changes required would be setting:

  1. fruit_basket.apple.seed.num_seeds = 5
  2. fruit_basket.apple.seed.seed_color = "brown"
  3. fruit_basket.apple.skin.skin_color= "green"

Is this possible? I'm imagining some sort of Class Params on each Factory that serve as 'message-passers'?

In reality, my conduit factory has around 5-10 RelatedFactories.

1

There are 1 best solutions below

1
Xelnor On

The idea would be to use factory.Trait:


class FruitBasketFactory(factory.django.DjangoModelFactory):
  class Params:
    apple_type_is_pinklady = factory.Trait(
      apple__skin__skin_color="green",
      apple__seed__seed__color="brown",
      apple__seed__num_seeds=5,
    )

As a side note, why is Seed pointing to Apple, instead of the other way around? Can there be several seeds/skins on the same apple?