Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django + Factory Boy: Use Trait to create other factory objects

Is it possible to use Traits (or anything else in Factory Boy) to trigger the creation of other factory objects? For example: In a User-Purchase-Product situation, I want to create a user and inform that this user has a product purchased with something simple like that:

UserFactory.create(with_purchased_product=True)

Because it feels like too much trouble to call UserFactory, ProductFactory and PurchaseFactory, then crate the relationship between them. There has to be a simpler way to do that.

Any help would be appreciated.

like image 246
user2937998 Avatar asked Nov 21 '17 17:11

user2937998


1 Answers

First, I'll be honest with you: I do not know if this is the best answer or if it follows the good practices of python.

Anyway, the solution that I found for this kind of scenario was to use post_generation.

import factory


class UserFactory(factory.DjangoModelFactory):
    class Meta:
        model = User

    name = factory.Faker('name'))

    @factory.post_generation
    def with_purchased_products(self, create, extracted, **kwargs):
        if extracted is not None:
            PurchaseFactory.create(user=self, with_products=extracted)


class PurchaseFactory(factory.DjangoModelFactory):
    class Meta:
        model = Purchase

    user = factory.SubFactory(UserFactory)

    @factory.post_generation
    def with_products(self, create, extracted, **kwargs):
        if extracted is not None:
            ProductFactory.create_batch(extracted, purchase=self)


class ProductFactory(factory.DjangoModelFactory):
    class Meta:
       model = Product

    purchase = factory.SubFactory(PurchaseFactory)

To make this work you just need to:

UserFactory.create(with_purchased_products=10)

And this is just a article that is helping learn more about Django tests with fakes & factories. Maybe can help you too.

like image 101
Pedro Paiva Avatar answered Nov 17 '22 20:11

Pedro Paiva