Tommy Wolfheart
Tommy Wolfheart

Reputation: 583

Is there a way to use a temporary non-field variable in factoryboy?

I am defining some factories for testing my e-commerce store. I have created a Faker provider that can return, for instance, a dictionary containing all the data for a random product.

I want to then use that dictionary to populate the fields in my factory. This is because the data in the dictionary is coherent. I don't want to create a factory with data that is not coherent e.g. a Product with name: "Short sleeve t-shirt" and then description: "Beautiful, comfortable shoes." Is there a way that I can implement something similar to

class ProductFactory(factory.django.DjangoModelFactory):
    temporary_product_dict = fake.product_dict_from_provider()
    
    name = temporary_product_dict["name"]
    description = temporary_product_dict["description"]
    category = temporary_product_dict["category"]
    ...

    class Meta:
        model = models.Product

When I do this exact thing, I get an error which tells me that temporary_product_dict is not an attribute of the Product model.

Upvotes: 3

Views: 627

Answers (2)

Darren Weber
Darren Weber

Reputation: 1674

I like the Params approach. Before learning about that approach, I used lazy attributes, where they can refer to previously declared and initialized attributes.

def get_random_city():
    # left as exercise
    pass


def get_city(zip_code: str):
    # left as exercise
    pass


class CityFactory():

    @factory.lazy_attribute
    def zip_code(self):
        while True:
            loc = get_random_city()
            if loc.postal_code and loc.place_name and loc.admin1_code:
                return loc.postal_code

    @factory.lazy_attribute
    def city(self):
        loc = get_city(self.zip_code)
        return loc.place_name

    @factory.lazy_attribute
    def state(self):
        loc = get_city(self.zip_code)
        return loc.admin1_code

Upvotes: 0

Tommy Wolfheart
Tommy Wolfheart

Reputation: 583

I have used class Params as follows:

class OptionTypeFactory(factory.django.DjangoModelFactory):
    """OptionType model factory."""

    class Meta:
        model = OptionType

    class Params:
        # Obtain coherent data for an option type from provider
        option_type = fake.product_option_type()

    name = Params.option_type["name"]
    display_name = Params.option_type["display_name"]
    index = Params.option_type["index"]
    created = datetime.datetime.strptime(
        Params.option_type["created"], "%Y-%m-%d %H:%M:%S"
    )
    updated = datetime.datetime.strptime(
        Params.option_type["updated"], "%Y-%m-%d %H:%M:%S"
    )


register(OptionTypeFactory)

Upvotes: 4

Related Questions