Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

factory boy: define field that depends on other field

How to define a field that depends on other field using factory-boy?

For instance, I'd like to define an email that depends on the first name and last name of an User.

I tried using the post_generation decorator. However, my system requires the definition of the email before creating the instance.

like image 993
jsmedmar Avatar asked Nov 27 '15 23:11

jsmedmar


People also ask

What does factory boy do?

The purpose of factory_boy is to provide a default way of getting a new instance, while still being able to override some fields on a per-call basis. This section will drive you through an overview of factory_boy's feature. New users are advised to spend a few minutes browsing through this list of useful helpers.

What is DjangoModelFactory?

DjangoModelFactory is a basic interface from factory_boy that gives "ORM powers" to your factories. It's main feature here is that it provides you with a common "create" and "build" strategies that you can use to generate objects in your tests.


1 Answers

Use LazyAttribute:

from the docs:

The LazyAttribute is a simple yet extremely powerful building brick for extending a Factory.

It takes as argument a method to call (usually a lambda); that method should accept the object being built as sole argument, and return a value.

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

    username = 'john'
    email = factory.LazyAttribute(lambda o: '%[email protected]' % o.username)

or the lazy_attribute decorator.

from the docs:

If a simple lambda isn’t enough, you may use the lazy_attribute() decorator instead.

This decorates an instance method that should take a single argument, self; the name of the method will be used as the name of the attribute to fill with the return value of the method:

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

    name = u"Jean"

    @factory.lazy_attribute
    def email(self):
        # Convert to plain ascii text
        clean_name = (unicodedata.normalize('NFKD', self.name)
                        .encode('ascii', 'ignore')
                        .decode('utf8'))
        return u'%[email protected]' % clean_name
like image 199
jsmedmar Avatar answered Oct 21 '22 11:10

jsmedmar