factoryboy man page

factoryboy — Factory Boy Documentation Latest VersionSupported Python versionsWheel statusLicense

factory_boy is a fixtures replacement based on thoughtbot's factory_girl.

As a fixtures replacement tool, it aims to replace static, hard to maintain fixtures with easy-to-use factories for complex object.

Instead of building an exhaustive test setup with every possible combination of corner cases, factory_boy allows you to use objects customized for the current test, while only declaring the test-specific fields:

class FooTests(unittest.TestCase):

    def test_with_factory_boy(self):
        # We need a 200€, paid order, shipping to australia, for a VIP customer
        order = OrderFactory(
            amount=200,
            status='PAID',
            customer__is_vip=True,
            address__country='AU',
        )
        # Run the tests here

    def test_without_factory_boy(self):
        address = Address(
            street="42 fubar street",
            zipcode="42Z42",
            city="Sydney",
            country="AU",
        )
        customer = Customer(
            first_name="John",
            last_name="Doe",
            phone="+1234",
            email="john.doe@example.org",
            active=True,
            is_vip=True,
            address=address,
        )
        # etc.

factory_boy is designed to work well with various ORMs (Django, Mogo, SQLAlchemy), and can easily be extended for other libraries.

Its main features include:

·
Straightforward declarative syntax
·
Chaining factory calls while retaining the global context
·
Support for multiple build strategies (saved/unsaved instances, stubbed objects)
·
Multiple factories per class support, including inheritance

Download

PyPI: https://pypi.python.org/pypi/factory_bo…

$ pip install factory_boy

Source: https://github.com/rbarrois/factory_boy/

$ git clone git://github.com/rbarrois/factory_boy/
$ python setup.py install

Usage

NOTE:

This section provides a quick summary of factory_boy features. A more detailed listing is available in the full documentation.

Defining factories

Factories declare a set of attributes used to instantiate an object. The class of the object must be defined in the model field of a class Meta: attribute:

import factory
from . import models

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

    first_name = 'John'
    last_name = 'Doe'
    admin = False

# Another, different, factory for the same object
class AdminFactory(factory.Factory):
    class Meta:
        model = models.User

    first_name = 'Admin'
    last_name = 'User'
    admin = True

Using factories

factory_boy supports several different build strategies: build, create, and stub:

# Returns a User instance that's not saved
user = UserFactory.build()

# Returns a saved User instance
user = UserFactory.create()

# Returns a stub object (just a bunch of attributes)
obj = UserFactory.stub()

You can use the Factory class as a shortcut for the default build strategy:

# Same as UserFactory.create()
user = UserFactory()

No matter which strategy is used, it's possible to override the defined attributes by passing keyword arguments:

# Build a User instance and override first_name
>>> user = UserFactory.build(first_name='Joe')
>>> user.first_name
"Joe"

It is also possible to create a bunch of objects in a single call:

>>> users = UserFactory.build_batch(10, first_name="Joe")
>>> len(users)
10
>>> [user.first_name for user in users]
["Joe", "Joe", "Joe", "Joe", "Joe", "Joe", "Joe", "Joe", "Joe", "Joe"]

Realistic, random values

Demos look better with random yet realistic values; and those realistic values can also help discover bugs. For this, factory_boy relies on the excellent fake-factory library:

class RandomUserFactory(factory.Factory):
    class Meta:
        model = models.User

    first_name = factory.Faker('first_name')
    last_name = factory.Faker('last_name')
>>> UserFactory()
<User: Lucy Murray>

NOTE:

Use of fully randomized data in tests is quickly a problem for reproducing broken builds. To that purpose, factory_boy provides helpers to handle the random seeds it uses.

Lazy Attributes

Most factory attributes can be added using static values that are evaluated when the factory is defined, but some attributes (such as fields whose value is computed from other elements) will need values assigned each time an instance is generated.

These "lazy" attributes can be added as follows:

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

    first_name = 'Joe'
    last_name = 'Blow'
    email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
    date_joined = factory.LazyFunction(datetime.now)
>>> UserFactory().email
"joe.blow@example.com"

NOTE:

LazyAttribute calls the function with the object being constructed as an argument, when LazyFunction does not send any argument.

Sequences

Unique values in a specific format (for example, e-mail addresses) can be generated using sequences. Sequences are defined by using Sequence or the decorator sequence:

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

    email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n))

>>> UserFactory().email
'person0@example.com'
>>> UserFactory().email
'person1@example.com'

Associations

Some objects have a complex field, that should itself be defined from a dedicated factories. This is handled by the SubFactory helper:

class PostFactory(factory.Factory):
    class Meta:
        model = models.Post

    author = factory.SubFactory(UserFactory)

The associated object's strategy will be used:

# Builds and saves a User and a Post
>>> post = PostFactory()
>>> post.id is None  # Post has been 'saved'
False
>>> post.author.id is None  # post.author has been saved
False

# Builds but does not save a User, and then builds but does not save a Post
>>> post = PostFactory.build()
>>> post.id is None
True
>>> post.author.id is None
True

ORM Support

factory_boy has specific support for a few ORMs, through specific factory.Factory subclasses:

·
Django, with factory.django.DjangoModelFactory
·
Mogo, with factory.mogo.MogoFactory
·
MongoEngine, with factory.mongoengine.MongoEngineFactory
·
SQLAlchemy, with factory.alchemy.SQLAlchemyModelFactory

Debugging factory_boy

Debugging factory_boy can be rather complex due to the long chains of calls. Detailed logging is available through the factory logger.

A helper, factory.debug(), is available to ease debugging:

with factory.debug():
    obj = TestModel2Factory()


import logging
logger = logging.getLogger('factory')
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)

This will yield messages similar to those (artificial indentation):

BaseFactory: Preparing tests.test_using.TestModel2Factory(extra={})
  LazyStub: Computing values for tests.test_using.TestModel2Factory(two=<OrderedDeclarationWrapper for <factory.declarations.SubFactory object at 0x1e15610>>)
    SubFactory: Instantiating tests.test_using.TestModelFactory(__containers=(<LazyStub for tests.test_using.TestModel2Factory>,), one=4), create=True
    BaseFactory: Preparing tests.test_using.TestModelFactory(extra={'__containers': (<LazyStub for tests.test_using.TestModel2Factory>,), 'one': 4})
      LazyStub: Computing values for tests.test_using.TestModelFactory(one=4)
      LazyStub: Computed values, got tests.test_using.TestModelFactory(one=4)
    BaseFactory: Generating tests.test_using.TestModelFactory(one=4)
  LazyStub: Computed values, got tests.test_using.TestModel2Factory(two=<tests.test_using.TestModel object at 0x1e15410>)
BaseFactory: Generating tests.test_using.TestModel2Factory(two=<tests.test_using.TestModel object at 0x1e15410>)

Contributing

factory_boy is distributed under the MIT License.

Issues should be opened through GitHub Issues; whenever possible, a pull request should be included. Questions and suggestions are welcome on the mailing-list.

All pull request should pass the test suite, which can be launched simply with:

$ make test

In order to test coverage, please use:

$ make coverage

To test with a specific framework version, you may use:

$ make DJANGO=1.9 test

Valid options are:

·
Django for Django
·
Mongoengine for mongoengine
·
ALCHEMY for SQLAlchemy

To avoid running mongoengine tests (e.g no mongo server installed), run:

$ make SKIP_MONGOENGINE=1 test

Contents, Indices and Tables

Introduction

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.

NOTE:

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.

Users looking for quick helpers may take a look at recipes, while those needing detailed documentation will be interested in the reference section.

Basic usage

Factories declare a set of attributes used to instantiate an object, whose class is defined in the class Meta's model attribute:

·
Subclass factory.Factory (or a more suitable subclass)
·
Add a class Meta: block
·
Set its model attribute to the target class
·
Add defaults for keyword args to pass to the associated class' __init__ method
import factory
from . import base

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

    firstname = "John"
    lastname = "Doe"

You may now get base.User instances trivially:

>>> john = UserFactory()
<User: John Doe>

It is also possible to override the defined attributes by passing keyword arguments to the factory:

>>> jack = UserFactory(firstname="Jack")
<User: Jack Doe>

A given class may be associated to many Factory subclasses:

class EnglishUserFactory(factory.Factory):
    class Meta:
        model = base.User

    firstname = "John"
    lastname = "Doe"
    lang = 'en'


class FrenchUserFactory(factory.Factory):
    class Meta:
        model = base.User

    firstname = "Jean"
    lastname = "Dupont"
    lang = 'fr'
>>> EnglishUserFactory()
<User: John Doe (en)>
>>> FrenchUserFactory()
<User: Jean Dupont (fr)>

Sequences

When a field has a unique key, each object generated by the factory should have a different value for that field. This is achieved with the Sequence declaration:

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

    username = factory.Sequence(lambda n: 'user%d' % n)
>>> UserFactory()
<User: user1>
>>> UserFactory()
<User: user2>

NOTE:

For more complex situations, you may also use the @sequence() decorator (note that self is not added as first parameter):

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

    @factory.sequence
    def username(n):
        return 'user%d' % n

LazyFunction

In simple cases, calling a function is enough to compute the value. If that function doesn't depend on the object being built, use LazyFunction to call that function; it should receive a function taking no argument and returning the value for the field:

class LogFactory(factory.Factory):
    class Meta:
        model = models.Log

    timestamp = factory.LazyFunction(datetime.now)
>>> LogFactory()
<Log: log at 2016-02-12 17:02:34>

>>> # The LazyFunction can be overriden
>>> LogFactory(timestamp=now - timedelta(days=1))
<Log: log at 2016-02-11 17:02:34>

NOTE:

For complex cases when you happen to write a specific function, the @lazy_attribute() decorator should be more appropriate.

LazyAttribute

Some fields may be deduced from others, for instance the email based on the username. The LazyAttribute handles such cases: it should receive a function taking the object being built and returning the value for the field:

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

    username = factory.Sequence(lambda n: 'user%d' % n)
    email = factory.LazyAttribute(lambda obj: '%s@example.com' % obj.username)
>>> UserFactory()
<User: user1 (user1@example.com)>

>>> # The LazyAttribute handles overridden fields
>>> UserFactory(username='john')
<User: john (john@example.com)>

>>> # They can be directly overridden as well
>>> UserFactory(email='doe@example.com')
<User: user3 (doe@example.com)>

NOTE:

As for Sequence, a @lazy_attribute() decorator is available:

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

    username = factory.Sequence(lambda n: 'user%d' % n)

    @factory.lazy_attribute
    def email(self):
        return '%s@example.com' % self.username

Inheritance

Once a "base" factory has been defined for a given class, alternate versions can be easily defined through subclassing.

The subclassed Factory will inherit all declarations from its parent, and update them with its own declarations:

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

    firstname = "John"
    lastname = "Doe"
    group = 'users'

class AdminFactory(UserFactory):
    admin = True
    group = 'admins'
>>> user = UserFactory()
>>> user
<User: John Doe>
>>> user.group
'users'

>>> admin = AdminFactory()
>>> admin
<User: John Doe (admin)>
>>> admin.group  # The AdminFactory field has overridden the base field
'admins'

Any argument of all factories in the chain can easily be overridden:

>>> super_admin = AdminFactory(group='superadmins', lastname="Lennon")
>>> super_admin
<User: John Lennon (admin)>
>>> super_admin.group  # Overridden at call time
'superadmins'

Non-kwarg arguments

Some classes take a few, non-kwarg arguments first.

This is handled by the inline_args attribute:

class MyFactory(factory.Factory):
    class Meta:
        model = MyClass
        inline_args = ('x', 'y')

    x = 1
    y = 2
    z = 3
>>> MyFactory(y=4)
<MyClass(1, 4, z=3)>

Altering a factory's behaviour: parameters and traits

Some classes are better described with a few, simple parameters, that aren't fields on the actual model. In that case, use a Params declaration:

class RentalFactory(factory.Factory):
    class Meta:
        model = Rental

    begin = factory.fuzzy.FuzzyDate(start_date=datetime.date(2000, 1, 1))
    end = factory.LazyAttribute(lambda o: o.begin + o.duration)

    class Params:
        duration = 12
>>> RentalFactory(duration=0)
<Rental: 2012-03-03 -> 2012-03-03>
>>> RentalFactory(duration=10)
<Rental: 2008-12-16 -> 2012-12-26>

When many fields should be updated based on a flag, use Traits instead:

class OrderFactory(factory.Factory):
    status = 'pending'
    shipped_by = None
    shipped_on = None

    class Meta:
        model = Order

    class Params:
        shipped = factory.Trait(
            status='shipped',
            shipped_by=factory.SubFactory(EmployeeFactory),
            shipped_on=factory.LazyFunction(datetime.date.today),
        )

A trait is toggled by a single boolean value:

>>> OrderFactory()
<Order: pending>
>>> OrderFactory(shipped=True)
<Order: shipped by John Doe on 2016-04-02>

Strategies

All factories support two built-in strategies:

·
build provides a local object
·
create instantiates a local object, and saves it to the database.

NOTE:

For 1.X versions, the create will actually call AssociatedClass.objects.create, as for a Django model.

Starting from 2.0, factory.Factory.create() simply calls AssociatedClass(**kwargs). You should use DjangoModelFactory for Django models.

When a Factory includes related fields (SubFactory, RelatedFactory), the parent's strategy will be pushed onto related factories.

Calling a Factory subclass will provide an object through the default strategy:

class MyFactory(factory.Factory):
    class Meta:
        model = MyClass
>>> MyFactory.create()
<MyFactory: X (saved)>

>>> MyFactory.build()
<MyFactory: X (unsaved)>

>>> MyFactory()  # equivalent to MyFactory.create()
<MyClass: X (saved)>

The default strategy can be changed by setting the class Meta strategy attribute.

Reference

This section offers an in-depth description of factory_boy features.

For internals and customization points, please refer to the internals section.

The Factory class

Meta options

class factory.FactoryOptions

New in version 2.4.0.

A Factory's behaviour can be tuned through a few settings.

For convenience, they are declared in a single class Meta attribute:

class MyFactory(factory.Factory):
    class Meta:
        model = MyObject
        abstract = False
model
This optional attribute describes the class of objects to generate.

If unset, it will be inherited from parent Factory subclasses.

New in version 2.4.0.
abstract

This attribute indicates that the Factory subclass should not be used to generate objects, but instead provides some extra defaults.

It will be automatically set to True if neither the Factory subclass nor its parents define the model attribute.

WARNING:

This flag is reset to False when a Factory subclasses another one if a model is set.

New in version 2.4.0.

inline_args

Some factories require non-keyword arguments to their __init__(). They should be listed, in order, in the inline_args attribute:

class UserFactory(factory.Factory):
    class Meta:
        model = User
        inline_args = ('login', 'email')

    login = 'john'
    email = factory.LazyAttribute(lambda o: '%s@example.com' % o.login)
    firstname = "John"
>>> UserFactory()
<User: john>
>>> User('john', 'john@example.com', firstname="John")  # actual call

New in version 2.4.0.

exclude

While writing a Factory for some object, it may be useful to have general fields helping defining others, but that should not be passed to the model class; for instance, a field named 'now' that would hold a reference time used by other objects.

Factory fields whose name are listed in exclude will be removed from the set of args/kwargs passed to the underlying class; they can be any valid factory_boy declaration:

class OrderFactory(factory.Factory):
    class Meta:
        model = Order
        exclude = ('now',)

    now = factory.LazyFunction(datetime.datetime.utcnow)
    started_at = factory.LazyAttribute(lambda o: o.now - datetime.timedelta(hours=1))
    paid_at = factory.LazyAttribute(lambda o: o.now - datetime.timedelta(minutes=50))
>>> OrderFactory()    # The value of 'now' isn't passed to Order()
<Order: started 2013-04-01 12:00:00, paid 2013-04-01 12:10:00>

>>> # An alternate value may be passed for 'now'
>>> OrderFactory(now=datetime.datetime(2013, 4, 1, 10))
<Order: started 2013-04-01 09:00:00, paid 2013-04-01 09:10:00>

New in version 2.4.0.

rename

Sometimes, a model expects a field with a name already used by one of Factory's methods.

In this case, the rename attributes allows to define renaming rules: the keys of the rename dict are those used in the Factory declarations, and their values the new name:

class ImageFactory(factory.Factory):
    # The model expects "attributes"
    form_attributes = ['thumbnail', 'black-and-white']

    class Meta:
        model = Image
        rename = {'form_attributes': 'attributes'}
strategy
Use this attribute to change the strategy used by a Factory. The default is CREATE_STRATEGY.

Attributes and methods

class factory.Factory

Class-level attributes:

Meta

_meta

New in version 2.4.0.

The FactoryOptions instance attached to a Factory class is available as a _meta attribute.

Params

New in version 2.7.0.

The extra parameters attached to a Factory are declared through a Params class. See the "Parameters" section for more information.

_options_class

New in version 2.4.0.

If a Factory subclass needs to define additional, extra options, it has to provide a custom FactoryOptions subclass.

A pointer to that custom class should be provided as _options_class so that the Factory-building metaclass can use it instead.

Base functions:

The Factory class provides a few methods for getting objects; the usual way being to simply call the class:

>>> UserFactory()               # Calls UserFactory.create()
>>> UserFactory(login='john')   # Calls UserFactory.create(login='john')

Under the hood, factory_boy will define the Factory __new__() method to call the default strategy of the Factory.

A specific strategy for getting instance can be selected by calling the adequate method:

classmethod build(cls, **kwargs)
Provides a new object, using the 'build' strategy.
classmethod build_batch(cls, size, **kwargs)
Provides a list of size instances from the Factory, through the 'build' strategy.
classmethod create(cls, **kwargs)
Provides a new object, using the 'create' strategy.
classmethod create_batch(cls, size, **kwargs)
Provides a list of size instances from the Factory, through the 'create' strategy.
classmethod stub(cls, **kwargs)
Provides a new stub
classmethod stub_batch(cls, size, **kwargs)
Provides a list of size stubs from the Factory.
classmethod generate(cls, strategy, **kwargs)
Provide a new instance, with the provided strategy.
classmethod generate_batch(cls, strategy, size, **kwargs)
Provides a list of size instances using the specified strategy.
classmethod simple_generate(cls, create, **kwargs)
Provide a new instance, either built (create=False) or created (create=True).
classmethod simple_generate_batch(cls, create, size, **kwargs)
Provides a list of size instances, either built or created according to create.

Extension points:

A Factory subclass may override a couple of class methods to adapt its behaviour:

classmethod _adjust_kwargs(cls, **kwargs)

The _adjust_kwargs() extension point allows for late fields tuning.

It is called once keyword arguments have been resolved and post-generation items removed, but before the inline_args extraction phase.

class UserFactory(factory.Factory):

    @classmethod
    def _adjust_kwargs(cls, **kwargs):
        # Ensure ``lastname`` is upper-case.
        kwargs['lastname'] = kwargs['lastname'].upper()
        return kwargs
classmethod _setup_next_sequence(cls)
This method will compute the first value to use for the sequence counter of this factory.

It is called when the first instance of the factory (or one of its subclasses) is created.

Subclasses may fetch the next free ID from the database, for instance.
classmethod _build(cls, model_class, *args, **kwargs)
This class method is called whenever a new instance needs to be built. It receives the model class (provided to model), and the positional and keyword arguments to use for the class once all has been computed.

Subclasses may override this for custom APIs.
classmethod _create(cls, model_class, *args, **kwargs)

The _create() method is called whenever an instance needs to be created. It receives the same arguments as _build().

Subclasses may override this for specific persistence backends:

class BaseBackendFactory(factory.Factory):
    class Meta:
        abstract = True  # Optional

    def _create(cls, model_class, *args, **kwargs):
        obj = model_class(*args, **kwargs)
        obj.save()
        return obj
classmethod _after_postgeneration(cls, obj, create, results=None)
Parameters
·
obj (object) -- The object just generated
·
create (bool) -- Whether the object was 'built' or 'created'
·
results (dict) -- Map of post-generation declaration name to call result

The _after_postgeneration() is called once post-generation declarations have been handled.

Its arguments allow to handle specifically some post-generation return values, for instance.

Advanced functions:

classmethod reset_sequence(cls, value=None, force=False)
Parameters
·
value (int) -- The value to reset the sequence to
·
force (bool) -- Whether to force-reset the sequence

Allows to reset the sequence counter for a Factory. The new value can be passed in as the value argument:

>>> SomeFactory.reset_sequence(4)
>>> SomeFactory._next_sequence
4

Since subclasses of a non-abstract Factory share the same sequence counter, special care needs to be taken when resetting the counter of such a subclass.

By default, reset_sequence() will raise a ValueError when called on a subclassed Factory subclass. This can be avoided by passing in the force=True flag:

>>> InheritedFactory.reset_sequence()
Traceback (most recent call last):
  File "factory_boy/tests/test_base.py", line 179, in test_reset_sequence_subclass_parent
    SubTestObjectFactory.reset_sequence()
  File "factory_boy/factory/base.py", line 250, in reset_sequence
    "Cannot reset the sequence of a factory subclass. "
ValueError: Cannot reset the sequence of a factory subclass. Please call reset_sequence() on the root factory, or call reset_sequence(forward=True).

>>> InheritedFactory.reset_sequence(force=True)
>>>

This is equivalent to calling reset_sequence() on the base factory in the chain.

Parameters

New in version 2.7.0.

Some models have many fields that can be summarized by a few parameters; for instance, a train with many cars — each complete with serial number, manufacturer, ...; or an order that can be pending/shipped/received, with a few fields to describe each step.

When building instances of such models, a couple of parameters can be enough to determine all other fields; this is handled by the Params section of a Factory declaration.

Simple parameters

Some factories only need little data:

class ConferenceFactory(factory.Factory):
    class Meta:
        model = Conference

    class Params:
        duration = 'short' # Or 'long'

    start_date = factory.fuzzy.FuzzyDate()
    end_date = factory.LazyAttribute(
        lambda o: o.start_date + datetime.timedelta(days=2 if o.duration == 'short' else 7)
    )
    sprints_start = factory.LazyAttribute(
        lambda o: o.end_date - datetime.timedelta(days=0 if o.duration == 'short' else 1)
    )
>>> Conference(duration='short')
<Conference: DUTH 2015 (2015-11-05 - 2015-11-08, sprints 2015-11-08)>
>>> Conference(duration='long')
<Conference: DjangoConEU 2016 (2016-03-30 - 2016-04-03, sprints 2016-04-02)>

Any simple parameter provided to the Factory.Params section is available to the whole factory, but not passed to the final class (similar to the exclude behavior).

Traits

class factory.Trait(**kwargs)

New in version 2.7.0.

A trait's parameters are the fields it sohuld alter when enabled.

For more complex situations, it is helpful to override a few fields at once:

class OrderFactory(factory.Factory):
    class Meta:
        model = Order

    state = 'pending'
    shipped_on = None
    shipped_by = None

    class Params:
        shipped = factory.Trait(
            state='shipped',
            shipped_on=datetime.date.today,
            shipped_by=factory.SubFactory(EmployeeFactory),
        )

Such a Trait is activated or disabled by a single boolean field:

>>> OrderFactory()
<Order: pending>
Order(state='pending')
>>> OrderFactory(shipped=True)
<Order: shipped by John Doe on 2016-04-02>

A Trait can be enabled/disabled by a Factory subclass:

class ShippedOrderFactory(OrderFactory):
    shipped = True

Values set in a Trait can be overridden by call-time values:

>>> OrderFactory(shipped=True, shipped_on=last_year)
<Order: shipped by John Doe on 2015-04-20>

Traits can be chained:

class OrderFactory(factory.Factory):
    class Meta:
        model = Order

    # Can be pending/shipping/received
    state = 'pending'
    shipped_on = None
    shipped_by = None
    received_on = None
    received_by = None

    class Params:
        shipped = factory.Trait(
            state='shipped',
            shipped_on=datetime.date.today,
            shipped_by=factory.SubFactory(EmployeeFactory),
        )
        received = factory.Trait(
            shipped=True,
            state='received',
            shipped_on=datetime.date.today - datetime.timedelta(days=4),
            received_on=datetime.date.today,
            received_by=factory.SubFactory(CustomerFactory),
        )
>>> OrderFactory(received=True)
<Order: shipped by John Doe on 2016-03-20, received by Joan Smith on 2016-04-02>

A Trait might be overridden in Factory subclasses:

class LocalOrderFactory(OrderFactory):

    class Params:
        received = factory.Trait(
            shipped=True,
            state='received',
            shipped_on=datetime.date.today - datetime.timedelta(days=1),
            received_on=datetime.date.today,
            received_by=factory.SubFactory(CustomerFactory),
        )
>>> LocalOrderFactory(received=True)
<Order: shipped by John Doe on 2016-04-01, received by Joan Smith on 2016-04-02>

NOTE:

When overriding a Trait, the whole declaration MUST be replaced.

Strategies

factory_boy supports two main strategies for generating instances, plus stubs.

factory.BUILD_STRATEGY
The 'build' strategy is used when an instance should be created, but not persisted to any datastore.

It is usually a simple call to the __init__() method of the model class.
factory.CREATE_STRATEGY

The 'create' strategy builds and saves an instance into its appropriate datastore.

This is the default strategy of factory_boy; it would typically instantiate an object, then save it:

>>> obj = self._associated_class(*args, **kwargs)
>>> obj.save()
>>> return obj

WARNING:

For backward compatibility reasons, the default behaviour of factory_boy is to call MyClass.objects.create(*args, **kwargs) when using the create strategy.

That policy will be used if the associated class has an objects attribute and the _create() classmethod of the Factory wasn't overridden.

factory.use_strategy(strategy)

Decorator

Change the default strategy of the decorated Factory to the chosen strategy:

@use_strategy(factory.BUILD_STRATEGY)
class UserBuildingFactory(UserFactory):
    pass
factory.STUB_STRATEGY
The 'stub' strategy is an exception in the factory_boy world: it doesn't return an instance of the model class, and actually doesn't require one to be present.

Instead, it returns an instance of StubObject whose attributes have been set according to the declarations.
class factory.StubObject(object)

A plain, stupid object. No method, no helpers, simply a bunch of attributes.

It is typically instantiated, then has its attributes set:

>>> obj = StubObject()
>>> obj.x = 1
>>> obj.y = 2
class factory.StubFactory(Factory)
An abstract Factory, with a default strategy set to STUB_STRATEGY.
factory.debug(logger='factory', stream=None)
Parameters
·
logger (str) -- The name of the logger to enable debug for
·
stream (file) -- The stream to send debug output to, defaults to sys.stderr

Context manager to help debugging factory_boy behavior. It will temporarily put the target logger (e.g 'factory') in debug mode, sending all output to :obj`~sys.stderr`; upon leaving the context, the logging levels are reset.

A typical use case is to understand what happens during a single factory call:

with factory.debug():
    obj = TestModel2Factory()

This will yield messages similar to those (artificial indentation):

BaseFactory: Preparing tests.test_using.TestModel2Factory(extra={})
  LazyStub: Computing values for tests.test_using.TestModel2Factory(two=<OrderedDeclarationWrapper for <factory.declarations.SubFactory object at 0x1e15610>>)
    SubFactory: Instantiating tests.test_using.TestModelFactory(__containers=(<LazyStub for tests.test_using.TestModel2Factory>,), one=4), create=True
    BaseFactory: Preparing tests.test_using.TestModelFactory(extra={'__containers': (<LazyStub for tests.test_using.TestModel2Factory>,), 'one': 4})
      LazyStub: Computing values for tests.test_using.TestModelFactory(one=4)
      LazyStub: Computed values, got tests.test_using.TestModelFactory(one=4)
    BaseFactory: Generating tests.test_using.TestModelFactory(one=4)
  LazyStub: Computed values, got tests.test_using.TestModel2Factory(two=<tests.test_using.TestModel object at 0x1e15410>)
BaseFactory: Generating tests.test_using.TestModel2Factory(two=<tests.test_using.TestModel object at 0x1e15410>)

Declarations

Faker

class factory.Faker(provider, locale=None, **kwargs)

In order to easily define realistic-looking factories, use the Faker attribute declaration.

This is a wrapper around fake-factory; its argument is the name of a fake-factory provider:

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

    name = factory.Faker('name')
>>> user = UserFactory()
>>> user.name
'Lucy Cechtelar'
locale

If a custom locale is required for one specific field, use the locale parameter:

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

    name = factory.Faker('name', locale='fr_FR')
>>> user = UserFactory()
>>> user.name
'Jean Valjean'
classmethod override_default_locale(cls, locale)

If the locale needs to be overridden for a whole test, use override_default_locale():

>>> with factory.Faker.override_default_locale('de_DE'):
...     UserFactory()
<User: Johannes Brahms>
classmethod add_provider(cls, locale=None)

Some projects may need to fake fields beyond those provided by fake-factory; in such cases, use factory.Faker.add_provider() to declare additional providers for those fields:

factory.Faker.add_provider(SmileyProvider)

class FaceFactory(factory.Factory):
    class Meta:
        model = Face

    smiley = factory.Faker('smiley')

LazyFunction

class factory.LazyFunction(method_to_call)

The LazyFunction is the simplest case where the value of an attribute does not depend on the object being built.

It takes as argument a method to call (function, lambda...); that method should not take any argument, though keyword arguments are safe but unused, and return a value.

class LogFactory(factory.Factory):
    class Meta:
        model = models.Log

    timestamp = factory.LazyFunction(datetime.now)
>>> LogFactory()
<Log: log at 2016-02-12 17:02:34>

>>> # The LazyFunction can be overriden
>>> LogFactory(timestamp=now - timedelta(days=1))
<Log: log at 2016-02-11 17:02:34>

Decorator

The class LazyFunction does not provide a decorator.

For complex cases, use LazyAttribute.lazy_attribute() directly.

LazyAttribute

class factory.LazyAttribute(method_to_call)

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: '%s@example.com' % o.username)
>>> u = UserFactory()
>>> u.email
'john@example.com'

>>> u = UserFactory(username='leo')
>>> u.email
'leo@example.com'

The object passed to LazyAttribute is not an instance of the target class, but instead a LazyStub: a temporary container that computes the value of all declared fields.

Decorator

factory.lazy_attribute()

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'%s@example.com' % clean_name
>>> joel = UserFactory(name=u"Joël")
>>> joel.email
u'joel@example.com'

Sequence

class factory.Sequence(lambda, type=int)

If a field should be unique, and thus different for all built instances, use a Sequence.

This declaration takes a single argument, a function accepting a single parameter - the current sequence counter - and returning the related value.

NOTE:

An extra kwarg argument, type, may be provided. This feature was deprecated in 1.3.0 and will be removed in 2.0.0.

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

    phone = factory.Sequence(lambda n: '123-555-%04d' % n)
>>> UserFactory().phone
'123-555-0001'
>>> UserFactory().phone
'123-555-0002'

Decorator

factory.sequence()

As with lazy_attribute(), a decorator is available for complex situations.

sequence() decorates an instance method, whose self method will actually be the sequence counter - this might be confusing:

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

    @factory.sequence
    def phone(n):
        a = n // 10000
        b = n % 10000
        return '%03d-555-%04d' % (a, b)
>>> UserFactory().phone
'000-555-9999'
>>> UserFactory().phone
'001-555-0000'

Sharing

The sequence counter is shared across all Sequence attributes of the Factory:

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

    phone = factory.Sequence(lambda n: '%04d' % n)
    office = factory.Sequence(lambda n: 'A23-B%03d' % n)
>>> u = UserFactory()
>>> u.phone, u.office
'0041', 'A23-B041'
>>> u2 = UserFactory()
>>> u2.phone, u2.office
'0042', 'A23-B042'

Inheritance

When a Factory inherits from another Factory and the model of the subclass inherits from the model of the parent, the sequence counter is shared across the Factory classes:

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

    phone = factory.Sequence(lambda n: '123-555-%04d' % n)


class EmployeeFactory(UserFactory):
    office_phone = factory.Sequence(lambda n: '%04d' % n)
>>> u = UserFactory()
>>> u.phone
'123-555-0001'

>>> e = EmployeeFactory()
>>> e.phone, e.office_phone
'123-555-0002', '0002'

>>> u2 = UserFactory()
>>> u2.phone
'123-555-0003'

Forcing a sequence counter

If a specific value of the sequence counter is required for one instance, the __sequence keyword argument should be passed to the factory method.

This will force the sequence counter during the call, without altering the class-level value.

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

    uid = factory.Sequence(int)
>>> UserFactory()
<User: 0>
>>> UserFactory()
<User: 1>
>>> UserFactory(__sequence=42)
<User: 42>

WARNING:

The impact of setting __sequence=n on a _batch call is undefined. Each generated instance may share a same counter, or use incremental values starting from the forced value.

LazyAttributeSequence

class factory.LazyAttributeSequence(method_to_call)

The LazyAttributeSequence declaration merges features of Sequence and LazyAttribute.

It takes a single argument, a function whose two parameters are, in order:

·
The object being built
·
The sequence counter
class UserFactory(factory.Factory):
    class Meta:
        model = User

    login = 'john'
    email = factory.LazyAttributeSequence(lambda o, n: '%s@s%d.example.com' % (o.login, n))
>>> UserFactory().email
'john@s1.example.com'
>>> UserFactory(login='jack').email
'jack@s2.example.com'

Decorator

factory.lazy_attribute_sequence(method_to_call)

As for lazy_attribute() and sequence(), the lazy_attribute_sequence() handles more complex cases:

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

    login = 'john'

    @lazy_attribute_sequence
    def email(self, n):
        bucket = n % 10
        return '%s@s%d.example.com' % (self.login, bucket)

SubFactory

class factory.SubFactory(factory, **kwargs)

This attribute declaration calls another Factory subclass, selecting the same build strategy and collecting extra kwargs in the process.

The SubFactory attribute should be called with:

·
A Factory subclass as first argument, or the fully qualified import path to that Factory (see Circular imports)
·
An optional set of keyword arguments that should be passed when calling that factory

NOTE:

When passing an actual Factory for the factory argument, make sure to pass the class and not instance (i.e no () after the class):

class FooFactory(factory.Factory):
    class Meta:
        model = Foo

    bar = factory.SubFactory(BarFactory)  # Not BarFactory()

Definition

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

    # Various fields
    first_name = 'John'
    last_name = factory.Sequence(lambda n: 'D%se' % ('o' * n))  # De, Doe, Dooe, Doooe, ...
    email = factory.LazyAttribute(lambda o: '%s.%s@example.org' % (o.first_name.lower(), o.last_name.lower()))

# A factory for an object with a 'User' field
class CompanyFactory(factory.Factory):
    class Meta:
        model = Company

    name = factory.Sequence(lambda n: 'FactoryBoyz' + 'z' * n)

    # Let's use our UserFactory to create that user, and override its first name.
    owner = factory.SubFactory(UserFactory, first_name='Jack')

Calling

The wrapping factory will call of the inner factory:

>>> c = CompanyFactory()
>>> c
<Company: FactoryBoyz>

# Notice that the first_name was overridden
>>> c.owner
<User: Jack De>
>>> c.owner.email
jack.de@example.org

Fields of the SubFactory may be overridden from the external factory:

>>> c = CompanyFactory(owner__first_name='Henry')
>>> c.owner
<User: Henry Doe>

# Notice that the updated first_name was propagated to the email LazyAttribute.
>>> c.owner.email
henry.doe@example.org

# It is also possible to override other fields of the SubFactory
>>> c = CompanyFactory(owner__last_name='Jones')
>>> c.owner
<User: Henry Jones>
>>> c.owner.email
henry.jones@example.org

Strategies

The strategy chosen for the external factory will be propagated to all subfactories:

>>> c = CompanyFactory()
>>> c.pk            # Saved to the database
3
>>> c.owner.pk      # Saved to the database
8

>>> c = CompanyFactory.build()
>>> c.pk            # Not saved
None
>>> c.owner.pk      # Not saved either
None

Circular imports

Some factories may rely on each other in a circular manner. This issue can be handled by passing the absolute import path to the target Factory to the SubFactory.

New in version 1.3.0.

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

    username = 'john'
    main_group = factory.SubFactory('users.factories.GroupFactory')

class GroupFactory(factory.Factory):
    class Meta:
        model = Group

    name = "MyGroup"
    owner = factory.SubFactory(UserFactory)

Obviously, such circular relationships require careful handling of loops:

>>> owner = UserFactory(main_group=None)
>>> UserFactory(main_group__owner=owner)
<john (group: MyGroup)>

SelfAttribute

class factory.SelfAttribute(dotted_path_to_attribute)

Some fields should reference another field of the object being constructed, or an attribute thereof.

This is performed by the SelfAttribute declaration. That declaration takes a single argument, a dot-delimited path to the attribute to fetch:

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

    birthdate = factory.Sequence(lambda n: datetime.date(2000, 1, 1) + datetime.timedelta(days=n))
    birthmonth = factory.SelfAttribute('birthdate.month')
>>> u = UserFactory()
>>> u.birthdate
date(2000, 3, 15)
>>> u.birthmonth
3

Parents

When used in conjunction with SubFactory, the SelfAttribute gains an "upward" semantic through the double-dot notation, as used in Python imports.

factory.SelfAttribute('..country.language') means "Select the language of the country of the Factory calling me".

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

    language = 'en'


class CompanyFactory(factory.Factory):
    class Meta:
        model = Company

    country = factory.SubFactory(CountryFactory)
    owner = factory.SubFactory(UserFactory, language=factory.SelfAttribute('..country.language'))
>>> company = CompanyFactory()
>>> company.country.language
'fr'
>>> company.owner.language
'fr'

Obviously, this "follow parents" ability also handles overriding some attributes on call:

>>> company = CompanyFactory(country=china)
>>> company.owner.language
'cn'

This feature is also available to LazyAttribute and LazyAttributeSequence, through the factory_parent attribute of the passed-in object:

class CompanyFactory(factory.Factory):
    class Meta:
        model = Company
    country = factory.SubFactory(CountryFactory)
    owner = factory.SubFactory(UserFactory,
        language=factory.LazyAttribute(lambda user: user.factory_parent.country.language),
    )

Iterator

class factory.Iterator(iterable, cycle=True, getter=None)

The Iterator declaration takes succesive values from the given iterable. When it is exhausted, it starts again from zero (unless cycle=False).

cycle
The cycle argument is only useful for advanced cases, where the provided iterable has no end (as wishing to cycle it means storing values in memory...).

New in version 1.3.0: The cycle argument is available as of v1.3.0; previous versions had a behaviour equivalent to cycle=False.
getter
A custom function called on each value returned by the iterable. See the Getter section for details.

New in version 1.3.0.
reset()
Reset the internal iterator used by the attribute, so that the next value will be the first value generated by the iterator.

May be called several times.

Each call to the factory will receive the next value from the iterable:

class UserFactory(factory.Factory)
    lang = factory.Iterator(['en', 'fr', 'es', 'it', 'de'])
>>> UserFactory().lang
'en'
>>> UserFactory().lang
'fr'

When a value is passed in for the argument, the iterator will not be advanced:

>>> UserFactory().lang
'en'
>>> UserFactory(lang='cn').lang
'cn'
>>> UserFactory().lang
'fr'

Getter

Some situations may reuse an existing iterable, using only some component. This is handled by the getter attribute: this is a function that accepts as sole parameter a value from the iterable, and returns an adequate value.

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

    # CATEGORY_CHOICES is a list of (key, title) tuples
    category = factory.Iterator(User.CATEGORY_CHOICES, getter=lambda c: c[0])

Decorator

factory.iterator(func)

When generating items of the iterator gets too complex for a simple list comprehension, use the iterator() decorator:

WARNING:

The decorated function takes no argument, notably no self parameter.

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

    @factory.iterator
    def name():
        with open('test/data/names.dat', 'r') as f:
            for line in f:
                yield line

Resetting

In order to start back at the first value in an Iterator, simply call the reset() method of that attribute (accessing it from the bare Factory subclass):

>>> UserFactory().lang
'en'
>>> UserFactory().lang
'fr'
>>> UserFactory.lang.reset()
>>> UserFactory().lang
'en'

Dict and List

When a factory expects lists or dicts as arguments, such values can be generated through the whole range of factory_boy declarations, with the Dict and List attributes:

class factory.Dict(params[, dict_factory=factory.DictFactory])

The Dict class is used for dict-like attributes. It receives as non-keyword argument a dictionary of fields to define, whose value may be any factory-enabled declarations:

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

    is_superuser = False
    roles = factory.Dict({
        'role1': True,
        'role2': False,
        'role3': factory.Iterator([True, False]),
        'admin': factory.SelfAttribute('..is_superuser'),
    })

NOTE:

Declarations used as a Dict values are evaluated within that Dict's context; this means that you must use the ..foo syntax to access fields defined at the factory level.

On the other hand, the Sequence counter is aligned on the containing factory's one.

The Dict behaviour can be tuned through the following parameters:

dict_factory
The actual factory to use for generating the dict can be set as a keyword argument, if an exotic dictionary-like object (SortedDict, ...) is required.
class factory.List(items[, list_factory=factory.ListFactory])

The List can be used for list-like attributes.

Internally, the fields are converted into a index=value dict, which makes it possible to override some values at use time:

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

    flags = factory.List([
        'user',
        'active',
        'admin',
    ])
>>> u = UserFactory(flags__2='superadmin')
>>> u.flags
['user', 'active', 'superadmin']

The List behaviour can be tuned through the following parameters:

list_factory
The actual factory to use for generating the list can be set as a keyword argument, if another type (tuple, set, ...) is required.

Post-generation hooks

Some objects expect additional method calls or complex processing for proper definition. For instance, a User may need to have a related Profile, where the Profile is built from the User object.

To support this pattern, factory_boy provides the following tools:
·
PostGenerationMethodCall: allows you to hook a particular attribute to a function call
·
PostGeneration: this class allows calling a given function with the generated object as argument
·
post_generation(): decorator performing the same functions as PostGeneration
·
RelatedFactory: this builds or creates a given factory after building/creating the first Factory.

Extracting parameters

All post-building hooks share a common base for picking parameters from the set of attributes passed to the Factory.

For instance, a PostGeneration hook is declared as post:

class SomeFactory(factory.Factory):
    class Meta:
        model = SomeObject

    @post_generation
    def post(obj, create, extracted, **kwargs):
        obj.set_origin(create)

When calling the factory, some arguments will be extracted for this method:

·
If a post argument is passed, it will be passed as the extracted field
·
Any argument starting with post__XYZ will be extracted, its post__ prefix removed, and added to the kwargs passed to the post-generation hook.

Extracted arguments won't be passed to the model class.

Thus, in the following call:

>>> SomeFactory(
    post=1,
    post_x=2,
    post__y=3,
    post__z__t=42,
)

The post hook will receive 1 as extracted and {'y': 3, 'z__t': 42} as keyword arguments; {'post_x': 2} will be passed to SomeFactory._meta.model.

RelatedFactory

class factory.RelatedFactory(factory, factory_related_name='', **kwargs)

A RelatedFactory behaves mostly like a SubFactory, with the main difference that the related Factory will be generated after the base Factory.

factory

As for SubFactory, the factory argument can be:

·
A Factory subclass
·
Or the fully qualified path to a Factory subclass (see Circular imports for details)
name
The generated object (where the RelatedFactory attribute will set) may be passed to the related factory if the factory_related_name parameter is set.

It will be passed as a keyword argument, using the name value as keyword:

NOTE:

When passing an actual Factory for the factory argument, make sure to pass the class and not instance (i.e no () after the class):

class FooFactory(factory.Factory):
    class Meta:
        model = Foo

    bar = factory.RelatedFactory(BarFactory)  # Not BarFactory()
class CityFactory(factory.Factory):
    class Meta:
        model = City

    capital_of = None
    name = "Toronto"

class CountryFactory(factory.Factory):
    class Meta:
        model = Country

    lang = 'fr'
    capital_city = factory.RelatedFactory(CityFactory, 'capital_of', name="Paris")
>>> france = CountryFactory()
>>> City.objects.get(capital_of=france)
<City: Paris>

Extra kwargs may be passed to the related factory, through the usual ATTR__SUBATTR syntax:

>>> england = CountryFactory(lang='en', capital_city__name="London")
>>> City.objects.get(capital_of=england)
<City: London>

If a value if passed for the RelatedFactory attribute, this disables RelatedFactory generation:

>>> france = CountryFactory()
>>> paris = City.objects.get()
>>> paris
<City: Paris>
>>> reunion = CountryFactory(capital_city=paris)
>>> City.objects.count()  # No new capital_city generated
1
>>> guyane = CountryFactory(capital_city=paris, capital_city__name='Kourou')
>>> City.objects.count()  # No new capital_city generated, ``name`` ignored.
1

NOTE:

The target of the RelatedFactory is evaluated after the initial factory has been instantiated. This means that calls to factory.SelfAttribute cannot go higher than this RelatedFactory:

class CountryFactory(factory.Factory):
    class Meta:
        model = Country

    lang = 'fr'
    capital_city = factory.RelatedFactory(CityFactory, 'capital_of',
        # factory.SelfAttribute('..lang') will crash, since the context of
        # ``CountryFactory`` has already been evaluated.
        main_lang=factory.SelfAttribute('capital_of.lang'),
    )

PostGeneration

class factory.PostGeneration(callable)

The PostGeneration declaration performs actions once the model object has been generated.

Its sole argument is a callable, that will be called once the base object has
been generated.

Once the base object has been generated, the provided callable will be called as callable(obj, create, extracted, **kwargs), where:

·
obj is the base object previously generated
·
create is a boolean indicating which strategy was used
·
extracted is None unless a value was passed in for the PostGeneration declaration at Factory declaration time
·
kwargs are any extra parameters passed as attr__key=value when calling the Factory:
class UserFactory(factory.Factory):
    class Meta:
        model = User

    login = 'john'
    make_mbox = factory.PostGeneration(
            lambda obj, create, extracted, **kwargs: os.makedirs(obj.login))

Decorator

factory.post_generation()

A decorator is also provided, decorating a single method accepting the same obj, created, extracted and keyword arguments as PostGeneration.

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

    login = 'john'

    @factory.post_generation
    def mbox(self, create, extracted, **kwargs):
        if not create:
            return
        path = extracted or os.path.join('/tmp/mbox/', self.login)
        os.path.makedirs(path)
        return path
>>> UserFactory.build()                  # Nothing was created
>>> UserFactory.create()                 # Creates dir /tmp/mbox/john
>>> UserFactory.create(login='jack')     # Creates dir /tmp/mbox/jack
>>> UserFactory.create(mbox='/tmp/alt')  # Creates dir /tmp/alt

PostGenerationMethodCall

class factory.PostGenerationMethodCall(method_name, *args, **kwargs)

The PostGenerationMethodCall declaration will call a method on the generated object just after instantiation. This declaration class provides a friendly means of generating attributes of a factory instance during initialization. The declaration is created using the following arguments:

method_name
The name of the method to call on the model object
args
The default set of unnamed arguments to pass to the method given in method_name
kwargs
The default set of keyword arguments to pass to the method given in method_name

Once the factory instance has been generated, the method specified in method_name will be called on the generated object with any arguments specified in the PostGenerationMethodCall declaration, by default.

For example, to set a default password on a generated User instance during instantiation, we could make a declaration for a password attribute like below:

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

    username = 'user'
    password = factory.PostGenerationMethodCall('set_password',
                                                'defaultpassword')

When we instantiate a user from the UserFactory, the factory will create a password attribute by calling User.set_password('defaultpassword'). Thus, by default, our users will have a password set to 'defaultpassword'.

>>> u = UserFactory()                             # Calls user.set_password('defaultpassword')
>>> u.check_password('defaultpassword')
True

If the PostGenerationMethodCall declaration contained no arguments or one argument, an overriding the value can be passed directly to the method through a keyword argument matching the attribute name. For example we can override the default password specified in the declaration above by simply passing in the desired password as a keyword argument to the factory during instantiation.

>>> other_u = UserFactory(password='different')   # Calls user.set_password('different')
>>> other_u.check_password('defaultpassword')
False
>>> other_u.check_password('different')
True

NOTE:

For Django models, unless the object method called by PostGenerationMethodCall saves the object back to the database, we will have to explicitly remember to save the object back if we performed a create().

>>> u = UserFactory.create()  # u.password has not been saved back to the database
>>> u.save()                  # we must remember to do it ourselves

We can avoid this by subclassing from DjangoModelFactory, instead, e.g.,

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

    username = 'user'
    password = factory.PostGenerationMethodCall('set_password',
                                                'defaultpassword')

If instead the PostGenerationMethodCall declaration uses two or more positional arguments, the overriding value must be an iterable. For example, if we declared the password attribute like the following,

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

    username = 'user'
    password = factory.PostGenerationMethodCall('set_password', '', 'sha1')

then we must be cautious to pass in an iterable for the password keyword argument when creating an instance from the factory:

>>> UserFactory()                           # Calls user.set_password('', 'sha1')
>>> UserFactory(password=('test', 'md5'))   # Calls user.set_password('test', 'md5')

>>> # Always pass in a good iterable:
>>> UserFactory(password=('test',))         # Calls user.set_password('test')
>>> UserFactory(password='test')            # Calls user.set_password('t', 'e', 's', 't')

NOTE:

While this setup provides sane and intuitive defaults for most users, it prevents passing more than one argument when the declaration used zero or one.

In such cases, users are advised to either resort to the more powerful PostGeneration or to add the second expected argument default value to the PostGenerationMethodCall declaration (PostGenerationMethodCall('method', 'x', 'y_that_is_the_default'))

Keywords extracted from the factory arguments are merged into the defaults present in the PostGenerationMethodCall declaration.

>>> UserFactory(password__disabled=True)    # Calls user.set_password('', 'sha1', disabled=True)

Module-level functions

Beyond the Factory class and the various Declarations classes and methods, factory_boy exposes a few module-level functions, mostly useful for lightweight factory generation.

Lightweight factory declaration

factory.make_factory(klass, **kwargs)

The make_factory() function takes a class, declarations as keyword arguments, and generates a new Factory for that class accordingly:

UserFactory = make_factory(User,
    login='john',
    email=factory.LazyAttribute(lambda u: '%s@example.com' % u.login),
)

# This is equivalent to:

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

    login = 'john'
    email = factory.LazyAttribute(lambda u: '%s@example.com' % u.login)

An alternate base class to Factory can be specified in the FACTORY_CLASS argument:

UserFactory = make_factory(models.User,
    login='john',
    email=factory.LazyAttribute(lambda u: '%s@example.com' % u.login),
    FACTORY_CLASS=factory.django.DjangoModelFactory,
)

# This is equivalent to:

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

    login = 'john'
    email = factory.LazyAttribute(lambda u: '%s@example.com' % u.login)

New in version 2.0.0: The FACTORY_CLASS kwarg was added in 2.0.0.

Instance building

The factory module provides a bunch of shortcuts for creating a factory and extracting instances from them:

factory.build(klass, FACTORY_CLASS=None, **kwargs)

factory.build_batch(klass, size, FACTORY_CLASS=None, **kwargs)

Create a factory for klass using declarations passed in kwargs; return an instance built from that factory, or a list of size instances (for build_batch()).

Parameters
·
klass (class) -- Class of the instance to build
·
size (int) -- Number of instances to build
·
kwargs -- Declarations to use for the generated factory
·
FACTORY_CLASS -- Alternate base class (instead of Factory)

factory.create(klass, FACTORY_CLASS=None, **kwargs)

factory.create_batch(klass, size, FACTORY_CLASS=None, **kwargs)

Create a factory for klass using declarations passed in kwargs; return an instance created from that factory, or a list of size instances (for create_batch()).

Parameters
·
klass (class) -- Class of the instance to create
·
size (int) -- Number of instances to create
·
kwargs -- Declarations to use for the generated factory
·
FACTORY_CLASS -- Alternate base class (instead of Factory)

factory.stub(klass, FACTORY_CLASS=None, **kwargs)

factory.stub_batch(klass, size, FACTORY_CLASS=None, **kwargs)

Create a factory for klass using declarations passed in kwargs; return an instance stubbed from that factory, or a list of size instances (for stub_batch()).

Parameters
·
klass (class) -- Class of the instance to stub
·
size (int) -- Number of instances to stub
·
kwargs -- Declarations to use for the generated factory
·
FACTORY_CLASS -- Alternate base class (instead of Factory)

factory.generate(klass, strategy, FACTORY_CLASS=None, **kwargs)

factory.generate_batch(klass, strategy, size, FACTORY_CLASS=None, **kwargs)

Create a factory for klass using declarations passed in kwargs; return an instance generated from that factory with the strategy strategy, or a list of size instances (for generate_batch()).

Parameters
·
klass (class) -- Class of the instance to generate
·
strategy (str) -- The strategy to use
·
size (int) -- Number of instances to generate
·
kwargs -- Declarations to use for the generated factory
·
FACTORY_CLASS -- Alternate base class (instead of Factory)

factory.simple_generate(klass, create, FACTORY_CLASS=None, **kwargs)

factory.simple_generate_batch(klass, create, size, FACTORY_CLASS=None, **kwargs)

Create a factory for klass using declarations passed in kwargs; return an instance generated from that factory according to the create flag, or a list of size instances (for simple_generate_batch()).

Parameters
·
klass (class) -- Class of the instance to generate
·
create (bool) -- Whether to build (False) or create (True) instances
·
size (int) -- Number of instances to generate
·
kwargs -- Declarations to use for the generated factory
·
FACTORY_CLASS -- Alternate base class (instead of Factory)

Using factory_boy with ORMs

factory_boy provides custom Factory subclasses for various ORMs, adding dedicated features.

Django

The first versions of factory_boy were designed specifically for Django, but the library has now evolved to be framework-independent.

Most features should thus feel quite familiar to Django users.

The DjangoModelFactory subclass

All factories for a Django Model should use the DjangoModelFactory base class.

class factory.django.DjangoModelFactory(factory.Factory)

Dedicated class for Django Model factories.

This class provides the following features:

·
The model attribute also supports the 'app.Model' syntax
·
create() uses Model.objects.create()
·
When using RelatedFactory or PostGeneration attributes, the base object will be saved once all post-generation hooks have run.

NOTE:

With Django versions 1.8.0 to 1.8.3, it was no longer possible to call .build() on a factory if this factory used a SubFactory pointing to another model: Django refused to set a ForeignKey to an unsaved Model instance.

See https://code.djangoproject.com/ticket/1… and https://code.djangoproject.com/ticket/2… for details.

class factory.django.DjangoOptions(factory.base.FactoryOptions)

The class Meta on a DjangoModelFactory supports extra parameters:

database

New in version 2.5.0.

All queries to the related model will be routed to the given database. It defaults to 'default'.

django_get_or_create

New in version 2.4.0.

Fields whose name are passed in this list will be used to perform a Model.objects.get_or_create() instead of the usual Model.objects.create():

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = 'myapp.User'  # Equivalent to ``model = myapp.models.User``
        django_get_or_create = ('username',)

    username = 'john'
>>> User.objects.all()
[]
>>> UserFactory()                   # Creates a new user
<User: john>
>>> User.objects.all()
[<User: john>]

>>> UserFactory()                   # Fetches the existing user
<User: john>
>>> User.objects.all()              # No new user!
[<User: john>]

>>> UserFactory(username='jack')    # Creates another user
<User: jack>
>>> User.objects.all()
[<User: john>, <User: jack>]

Extra fields

class factory.django.FileField

Custom declarations for django.db.models.FileField

__init__(self, from_path='', from_file='', data=b'', filename='example.dat')
Parameters
·
from_path (str) -- Use data from the file located at from_path, and keep its filename
·
from_file (file) -- Use the contents of the provided file object; use its filename if available, unless filename is also provided.
·
data (bytes) -- Use the provided bytes as file contents
·
filename (str) -- The filename for the FileField

NOTE:

If the value None was passed for the FileField field, this will disable field generation:

class MyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.MyModel

    the_file = factory.django.FileField(filename='the_file.dat')
>>> MyFactory(the_file__data=b'uhuh').the_file.read()
b'uhuh'
>>> MyFactory(the_file=None).the_file
None
class factory.django.ImageField

Custom declarations for django.db.models.ImageField

__init__(self, from_path='', from_file='', filename='example.jpg', width=100, height=100, color='green', format='JPEG')
Parameters
·
from_path (str) -- Use data from the file located at from_path, and keep its filename
·
from_file (file) -- Use the contents of the provided file object; use its filename if available
·
filename (str) -- The filename for the ImageField
·
width (int) -- The width of the generated image (default: 100)
·
height (int) -- The height of the generated image (default: 100)
·
color (str) -- The color of the generated image (default: 'green')
·
format (str) -- The image format (as supported by PIL) (default: 'JPEG')

NOTE:

If the value None was passed for the FileField field, this will disable field generation:

NOTE:

Just as Django's django.db.models.ImageField requires the Python Imaging Library, this ImageField requires it too.

class MyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.MyModel

    the_image = factory.django.ImageField(color='blue')
>>> MyFactory(the_image__width=42).the_image.width
42
>>> MyFactory(the_image=None).the_image
None

Disabling signals

Signals are often used to plug some custom code into external components code; for instance to create Profile objects on-the-fly when a new User object is saved.

This may interfere with finely tuned factories, which would create both using RelatedFactory.

To work around this problem, use the mute_signals() decorator/context manager:

factory.django.mute_signals(signal1, ...)
Disable the list of selected signals when calling the factory, and reactivate them upon leaving.
# foo/factories.py

import factory
import factory.django

from . import models
from . import signals

@factory.django.mute_signals(signals.pre_save, signals.post_save)
class FooFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Foo

    # ...

def make_chain():
    with factory.django.mute_signals(signals.pre_save, signals.post_save):
        # pre_save/post_save won't be called here.
        return SomeFactory(), SomeOtherFactory()

Mogo

factory_boy supports Mogo-style models, through the MogoFactory class.

Mogo is a wrapper around the pymongo library for MongoDB.

class factory.mogo.MogoFactory(factory.Factory)

Dedicated class for Mogo models.

This class provides the following features:

·
build() calls a model's new() method
·
create() builds an instance through new() then saves it.

MongoEngine

factory_boy supports MongoEngine-style models, through the MongoEngineFactory class.

mongoengine is a wrapper around the pymongo library for MongoDB.

class factory.mongoengine.MongoEngineFactory(factory.Factory)

Dedicated class for MongoEngine models.

This class provides the following features:

·
build() calls a model's __init__ method
·
create() builds an instance through __init__ then saves it.

NOTE:

If the associated class <factory.FactoryOptions.model is a mongoengine.EmbeddedDocument, the create() function won't "save" it, since this wouldn't make sense.

This feature makes it possible to use SubFactory to create embedded document.

A minimalist example:

import mongoengine

class Address(mongoengine.EmbeddedDocument):
    street = mongoengine.StringField()

class Person(mongoengine.Document):
    name = mongoengine.StringField()
    address = mongoengine.EmbeddedDocumentField(Address)

import factory

class AddressFactory(factory.mongoengine.MongoEngineFactory):
    class Meta:
        model = Address

    street = factory.Sequence(lambda n: 'street%d' % n)

class PersonFactory(factory.mongoengine.MongoEngineFactory):
    class Meta:
        model = Person

    name = factory.Sequence(lambda n: 'name%d' % n)
    address = factory.SubFactory(AddressFactory)

SQLAlchemy

Factoy_boy also supports SQLAlchemy models through the SQLAlchemyModelFactory class.

To work, this class needs an SQLAlchemy session object affected to the Meta.sqlalchemy_session attribute.

class factory.alchemy.SQLAlchemyModelFactory(factory.Factory)

Dedicated class for SQLAlchemy models.

This class provides the following features:

·
create() uses sqlalchemy.orm.session.Session.add()
class factory.alchemy.SQLAlchemyOptions(factory.base.FactoryOptions)

In addition to the usual parameters available in class Meta, a SQLAlchemyModelFactory also supports the following settings:

sqlalchemy_session
SQLAlchemy session to use to communicate with the database when creating an object through this SQLAlchemyModelFactory.
force_flush
Force a session flush() at the end of _create().

A (very) simple example:

from sqlalchemy import Column, Integer, Unicode, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite://')
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()


class User(Base):
    """ A SQLAlchemy simple model class who represents a user """
    __tablename__ = 'UserTable'

    id = Column(Integer(), primary_key=True)
    name = Column(Unicode(20))

Base.metadata.create_all(engine)

import factory

class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = User
        sqlalchemy_session = session   # the SQLAlchemy session object

    id = factory.Sequence(lambda n: n)
    name = factory.Sequence(lambda n: u'User %d' % n)
>>> session.query(User).all()
[]
>>> UserFactory()
<User: User 1>
>>> session.query(User).all()
[<User: User 1>]

Managing sessions

Since SQLAlchemy is a general purpose library, there is no "global" session management system.

The most common pattern when working with unit tests and factory_boy is to use SQLAlchemy's sqlalchemy.orm.scoping.scoped_session:

·
The test runner configures some project-wide scoped_session
·
Each SQLAlchemyModelFactory subclass uses this scoped_session as its sqlalchemy_session
·
The tearDown() method of tests calls Session.remove to reset the session.

NOTE:

See the excellent SQLAlchemy guide on scoped_session for details of scoped_session's usage.

The basic idea is that declarative parts of the code (including factories) need a simple way to access the "current session", but that session will only be created and configured at a later point.

The scoped_session handles this, by virtue of only creating the session when a query is sent to the database.

Here is an example layout:

·
A global (test-only?) file holds the scoped_session:
# myprojet/test/common.py

from sqlalchemy import orm
Session = orm.scoped_session(orm.sessionmaker())
·
All factory access it:
# myproject/factories.py

import factory
import factory.alchemy

from . import models
from .test import common

class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = models.User

        # Use the not-so-global scoped_session
        # Warning: DO NOT USE common.Session()!
        sqlalchemy_session = common.Session

    name = factory.Sequence(lambda n: "User %d" % n)
·
The test runner configures the scoped_session when it starts:
# myproject/test/runtests.py

import sqlalchemy

from . import common

def runtests():
    engine = sqlalchemy.create_engine('sqlite://')

    # It's a scoped_session, and now is the time to configure it.
    common.Session.configure(bind=engine)

    run_the_tests
·
test cases use this scoped_session, and clear it after each test (for isolation):
# myproject/test/test_stuff.py

import unittest

from . import common

class MyTest(unittest.TestCase):

    def setUp(self):
        # Prepare a new, clean session
        self.session = common.Session()

    def test_something(self):
        u = factories.UserFactory()
        self.assertEqual([u], self.session.query(User).all())

    def tearDown(self):
        # Rollback the session => no changes to the database
        self.session.rollback()
        # Remove it, so that the next test gets a new Session()
        common.Session.remove()

Common recipes

NOTE:

Most recipes below take on Django model examples, but can also be used on their own.

Dependent objects (ForeignKey)

When one attribute is actually a complex field (e.g a ForeignKey to another Model), use the SubFactory declaration:

# models.py
class User(models.Model):
    first_name = models.CharField()
    group = models.ForeignKey(Group)


# factories.py
import factory
from . import models

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

    first_name = factory.Sequence(lambda n: "Agent %03d" % n)
    group = factory.SubFactory(GroupFactory)

Choosing from a populated table

If the target of the ForeignKey should be chosen from a pre-populated table (e.g django.contrib.contenttypes.models.ContentType), simply use a factory.Iterator on the chosen queryset:

import factory, factory.django
from . import models

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

    language = factory.Iterator(models.Language.objects.all())

Here, models.Language.objects.all() won't be evaluated until the first call to UserFactory; thus avoiding DB queries at import time.

Reverse dependencies (reverse ForeignKey)

When a related object should be created upon object creation (e.g a reverse ForeignKey from another Model), use a RelatedFactory declaration:

# models.py
class User(models.Model):
    pass

class UserLog(models.Model):
    user = models.ForeignKey(User)
    action = models.CharField()


# factories.py
class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.User

    log = factory.RelatedFactory(UserLogFactory, 'user', action=models.UserLog.ACTION_CREATE)

When a UserFactory is instantiated, factory_boy will call UserLogFactory(user=that_user, action=...) just before returning the created User.

Example: Django's Profile

Django (<1.5) provided a mechanism to attach a Profile to a User instance, using a OneToOneField from the Profile to the User.

A typical way to create those profiles was to hook a post-save signal to the User model.

factory_boy allows to define attributes of such profiles dynamically when creating a User:

class ProfileFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = my_models.Profile

    title = 'Dr'
    # We pass in profile=None to prevent UserFactory from creating another profile
    # (this disables the RelatedFactory)
    user = factory.SubFactory('app.factories.UserFactory', profile=None)

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

    username = factory.Sequence(lambda n: "user_%d" % n)

    # We pass in 'user' to link the generated Profile to our just-generated User
    # This will call ProfileFactory(user=our_new_user), thus skipping the SubFactory.
    profile = factory.RelatedFactory(ProfileFactory, 'user')

    @classmethod
    def _generate(cls, create, attrs):
        """Override the default _generate() to disable the post-save signal."""

        # Note: If the signal was defined with a dispatch_uid, include that in both calls.
        post_save.disconnect(handler_create_user_profile, auth_models.User)
        user = super(UserFactory, cls)._generate(create, attrs)
        post_save.connect(handler_create_user_profile, auth_models.User)
        return user
>>> u = UserFactory(profile__title=u"Lord")
>>> u.get_profile().title
u"Lord"

Such behaviour can be extended to other situations where a signal interferes with factory_boy related factories.

NOTE:

When any RelatedFactory or post_generation attribute is defined on the DjangoModelFactory subclass, a second save() is performed after the call to _create().

Code working with signals should thus override the _generate() method.

Simple Many-to-many relationship

Building the adequate link between two models depends heavily on the use case; factory_boy doesn't provide a "all in one tools" as for SubFactory or RelatedFactory, users will have to craft their own depending on the model.

The base building block for this feature is the post_generation hook:

# models.py
class Group(models.Model):
    name = models.CharField()

class User(models.Model):
    name = models.CharField()
    groups = models.ManyToManyField(Group)


# factories.py
class GroupFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Group

    name = factory.Sequence(lambda n: "Group #%s" % n)

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

    name = "John Doe"

    @factory.post_generation
    def groups(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        if extracted:
            # A list of groups were passed in, use them
            for group in extracted:
                self.groups.add(group)

When calling UserFactory() or UserFactory.build(), no group binding will be created.

But when UserFactory.create(groups=(group1, group2, group3)) is called, the groups declaration will add passed in groups to the set of groups for the user.

Many-to-many relation with a 'through'

If only one link is required, this can be simply performed with a RelatedFactory. If more links are needed, simply add more RelatedFactory declarations:

# models.py
class User(models.Model):
    name = models.CharField()

class Group(models.Model):
    name = models.CharField()
    members = models.ManyToManyField(User, through='GroupLevel')

class GroupLevel(models.Model):
    user = models.ForeignKey(User)
    group = models.ForeignKey(Group)
    rank = models.IntegerField()


# factories.py
class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.User

    name = "John Doe"

class GroupFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Group

    name = "Admins"

class GroupLevelFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.GroupLevel

    user = factory.SubFactory(UserFactory)
    group = factory.SubFactory(GroupFactory)
    rank = 1

class UserWithGroupFactory(UserFactory):
    membership = factory.RelatedFactory(GroupLevelFactory, 'user')

class UserWith2GroupsFactory(UserFactory):
    membership1 = factory.RelatedFactory(GroupLevelFactory, 'user', group__name='Group1')
    membership2 = factory.RelatedFactory(GroupLevelFactory, 'user', group__name='Group2')

Whenever the UserWithGroupFactory is called, it will, as a post-generation hook, call the GroupLevelFactory, passing the generated user as a user field:

1.
UserWithGroupFactory() generates a User instance, obj
2.
It calls GroupLevelFactory(user=obj)
3.
It returns obj

When using the UserWith2GroupsFactory, that behavior becomes:

1.
UserWith2GroupsFactory() generates a User instance, obj
2.
It calls GroupLevelFactory(user=obj, group__name='Group1')
3.
It calls GroupLevelFactory(user=obj, group__name='Group2')
4.
It returns obj

Copying fields to a SubFactory

When a field of a related class should match one of the container:

# models.py
class Country(models.Model):
    name = models.CharField()
    lang = models.CharField()

class User(models.Model):
    name = models.CharField()
    lang = models.CharField()
    country = models.ForeignKey(Country)

class Company(models.Model):
    name = models.CharField()
    owner = models.ForeignKey(User)
    country = models.ForeignKey(Country)

Here, we want:

·
The User to have the lang of its country (factory.SelfAttribute('country.lang'))
·
The Company owner to live in the country of the company (factory.SelfAttribute('..country'))
# factories.py
class CountryFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Country

    name = factory.Iterator(["France", "Italy", "Spain"])
    lang = factory.Iterator(['fr', 'it', 'es'])

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

    name = "John"
    lang = factory.SelfAttribute('country.lang')
    country = factory.SubFactory(CountryFactory)

class CompanyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Company

    name = "ACME, Inc."
    country = factory.SubFactory(CountryFactory)
    owner = factory.SubFactory(UserFactory, country=factory.SelfAttribute('..country'))

If the value of a field on the child factory is indirectly derived from a field on the parent factory, you will need to use LazyAttribute and poke the "factory_parent" attribute.

This time, we want the company owner to live in a country neighboring the country of the company:

class CompanyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Company

    name = "ACME, Inc."
    country = factory.SubFactory(CountryFactory)
    owner = factory.SubFactory(UserFactory,
        country=factory.LazyAttribute(lambda o: get_random_neighbor(o.factory_parent.country)))

Custom manager methods

Sometimes you need a factory to call a specific manager method other then the default Model.objects.create() method:

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

    username = "l7d8s"
    email = "my_name@example.com"
    password = "my_password"

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        """Override the default ``_create`` with our custom call."""
        manager = cls._get_manager(model_class)
        # The default would use ``manager.create(*args, **kwargs)``
        return manager.create_user(*args, **kwargs)

Forcing the sequence counter

A common pattern with factory_boy is to use a factory.Sequence declaration to provide varying values to attributes declared as unique.

However, it is sometimes useful to force a given value to the counter, for instance to ensure that tests are properly reproductible.

factory_boy provides a few hooks for this:

Forcing the value on a per-call basis

In order to force the counter for a specific Factory instantiation, just pass the value in the __sequence=42 parameter:

class AccountFactory(factory.Factory):
    class Meta:
        model = Account
    uid = factory.Sequence(lambda n: n)
    name = "Test"
>>> obj1 = AccountFactory(name="John Doe", __sequence=10)
>>> obj1.uid  # Taken from the __sequence counter
10
>>> obj2 = AccountFactory(name="Jane Doe")
>>> obj2.uid  # The base sequence counter hasn't changed
1
Resetting the counter globally

If all calls for a factory must start from a deterministic number, use factory.Factory.reset_sequence(); this will reset the counter to its initial value (as defined by factory.Factory._setup_next_sequence()).

>>> AccountFactory().uid
1
>>> AccountFactory().uid
2
>>> AccountFactory.reset_sequence()
>>> AccountFactory().uid  # Reset to the initial value
1
>>> AccountFactory().uid
2

It is also possible to reset the counter to a specific value:

>>> AccountFactory.reset_sequence(10)
>>> AccountFactory().uid
10
>>> AccountFactory().uid
11

This recipe is most useful in a TestCase's setUp() method.

Forcing the initial value for all projects

The sequence counter of a Factory can also be set automatically upon the first call through the _setup_next_sequence() method; this helps when the objects's attributes mustn't conflict with pre-existing data.

A typical example is to ensure that running a Python script twice will create non-conflicting objects, by setting up the counter to "max used value plus one":

class AccountFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Account

    @classmethod
    def _setup_next_sequence(cls):
        try:
            return models.Accounts.objects.latest('uid').uid + 1
        except models.Account.DoesNotExist:
            return 1
>>> Account.objects.create(uid=42, name="Blah")
>>> AccountFactory.create()  # Sets up the account number based on the latest uid
<Account uid=43, name=Test>

Converting a factory's output to a dict

In order to inject some data to, say, a REST API, it can be useful to fetch the factory's data as a dict.

Internally, a factory will:

1.
Merge declarations and overrides from all sources (class definition, call parameters, ...)
2.
Resolve them into a dict
3.
Pass that dict as keyword arguments to the model's build / create function

In order to get a dict, we'll just have to swap the model; the easiest way is to use factory.build():

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

    first_name = factory.Sequence(lambda n: "Agent %03d" % n)
    username = factory.Faker('username')
>>> factory.build(dict, FACTORY_CLASS=UserFactory)
{'first_name': "Agent 001", 'username': 'john_doe'}

Fuzzy attributes

NOTE:

Now that FactoryBoy includes the factory.Faker class, most of these built-in fuzzers are deprecated in favor of their Faker equivalents. Further discussion here: https://github.com/rbarrois/factory_boy…

Some tests may be interested in testing with fuzzy, random values.

This is handled by the factory.fuzzy module, which provides a few random declarations.

NOTE:

Use import factory.fuzzy to load this module.

FuzzyAttribute

class factory.fuzzy.FuzzyAttribute

The FuzzyAttribute uses an arbitrary callable as fuzzer. It is expected that successive calls of that function return various values.

fuzzer
The callable that generates random values

FuzzyText

class factory.fuzzy.FuzzyText(length=12, chars=string.ascii_letters, prefix='')

The FuzzyText fuzzer yields random strings beginning with the given prefix, followed by length charactes chosen from the chars character set, and ending with the given suffix.

length
int, the length of the random part
prefix
text, an optional prefix to prepend to the random part
suffix
text, an optional suffix to append to the random part
chars
char iterable, the chars to choose from; defaults to the list of ascii
letters and numbers.

FuzzyChoice

class factory.fuzzy.FuzzyChoice(choices)

The FuzzyChoice fuzzer yields random choices from the given iterable.

NOTE:

The passed in choices will be converted into a list upon first use, not at declaration time.

This allows passing in, for instance, a Django queryset that will only hit the database during the database, not at import time.

choices
The list of choices to select randomly

FuzzyInteger

class factory.fuzzy.FuzzyInteger(low[, high[, step]])

The FuzzyInteger fuzzer generates random integers within a given inclusive range.

The low bound may be omitted, in which case it defaults to 0:

>>> fi = FuzzyInteger(0, 42)
>>> fi.low, fi.high
0, 42

>>> fi = FuzzyInteger(42)
>>> fi.low, fi.high
0, 42
low
int, the inclusive lower bound of generated integers
high
int, the inclusive higher bound of generated integers
step
int, the step between values in the range; for instance, a FuzzyInteger(0, 42, step=3) might only yield values from [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42].

FuzzyDecimal

class factory.fuzzy.FuzzyDecimal(low[, high[, precision=2]])

The FuzzyDecimal fuzzer generates random decimals within a given inclusive range.

The low bound may be omitted, in which case it defaults to 0:

>>> FuzzyDecimal(0.5, 42.7)
>>> fi.low, fi.high
0.5, 42.7

>>> fi = FuzzyDecimal(42.7)
>>> fi.low, fi.high
0.0, 42.7

>>> fi = FuzzyDecimal(0.5, 42.7, 3)
>>> fi.low, fi.high, fi.precision
0.5, 42.7, 3
low
decimal, the inclusive lower bound of generated decimals
high
decimal, the inclusive higher bound of generated decimals

precision

int, the number of digits to generate after the dot. The default is 2 digits.

FuzzyFloat

class factory.fuzzy.FuzzyFloat(low[, high])

The FuzzyFloat fuzzer provides random float objects within a given inclusive range.

>>> FuzzyFloat(0.5, 42.7)
>>> fi.low, fi.high
0.5, 42.7

>>> fi = FuzzyFloat(42.7)
>>> fi.low, fi.high
0.0, 42.7
low
decimal, the inclusive lower bound of generated floats
high
decimal, the inclusive higher bound of generated floats

FuzzyDate

class factory.fuzzy.FuzzyDate(start_date[, end_date])

The FuzzyDate fuzzer generates random dates within a given inclusive range.

The end_date bound may be omitted, in which case it defaults to the current date:

>>> fd = FuzzyDate(datetime.date(2008, 1, 1))
>>> fd.start_date, fd.end_date
datetime.date(2008, 1, 1), datetime.date(2013, 4, 16)
start_date
datetime.date, the inclusive lower bound of generated dates
end_date
datetime.date, the inclusive higher bound of generated dates

FuzzyDateTime

class factory.fuzzy.FuzzyDateTime(start_dt[, end_dt], force_year=None, force_month=None, force_day=None, force_hour=None, force_minute=None, force_second=None, force_microsecond=None)

The FuzzyDateTime fuzzer generates random timezone-aware datetime within a given inclusive range.

The end_dt bound may be omitted, in which case it defaults to datetime.datetime.now() localized into the UTC timezone.

>>> fdt = FuzzyDateTime(datetime.datetime(2008, 1, 1, tzinfo=UTC))
>>> fdt.start_dt, fdt.end_dt
datetime.datetime(2008, 1, 1, tzinfo=UTC), datetime.datetime(2013, 4, 21, 19, 13, 32, 458487, tzinfo=UTC)

The force_XXX keyword arguments force the related value of generated datetimes:

>>> fdt = FuzzyDateTime(datetime.datetime(2008, 1, 1, tzinfo=UTC), datetime.datetime(2009, 1, 1, tzinfo=UTC),
...     force_day=3, force_second=42)
>>> fdt.evaluate(2, None, False)  # Actual code used by ``SomeFactory.build()``
datetime.datetime(2008, 5, 3, 12, 13, 42, 124848, tzinfo=UTC)
start_dt
datetime.datetime, the inclusive lower bound of generated datetimes
end_dt
datetime.datetime, the inclusive upper bound of generated datetimes
force_year
int or None; if set, forces the year of generated datetime.
force_month
int or None; if set, forces the month of generated datetime.
force_day
int or None; if set, forces the day of generated datetime.
force_hour
int or None; if set, forces the hour of generated datetime.
force_minute
int or None; if set, forces the minute of generated datetime.
force_second
int or None; if set, forces the second of generated datetime.
force_microsecond
int or None; if set, forces the microsecond of generated datetime.

FuzzyNaiveDateTime

class factory.fuzzy.FuzzyNaiveDateTime(start_dt[, end_dt], force_year=None, force_month=None, force_day=None, force_hour=None, force_minute=None, force_second=None, force_microsecond=None)

The FuzzyNaiveDateTime fuzzer generates random naive datetime within a given inclusive range.

The end_dt bound may be omitted, in which case it defaults to datetime.datetime.now():

>>> fdt = FuzzyNaiveDateTime(datetime.datetime(2008, 1, 1))
>>> fdt.start_dt, fdt.end_dt
datetime.datetime(2008, 1, 1), datetime.datetime(2013, 4, 21, 19, 13, 32, 458487)

The force_XXX keyword arguments force the related value of generated datetimes:

>>> fdt = FuzzyNaiveDateTime(datetime.datetime(2008, 1, 1), datetime.datetime(2009, 1, 1),
...     force_day=3, force_second=42)
>>> fdt.evaluate(2, None, False)  # Actual code used by ``SomeFactory.build()``
datetime.datetime(2008, 5, 3, 12, 13, 42, 124848)
start_dt
datetime.datetime, the inclusive lower bound of generated datetimes
end_dt
datetime.datetime, the inclusive upper bound of generated datetimes
force_year
int or None; if set, forces the year of generated datetime.
force_month
int or None; if set, forces the month of generated datetime.
force_day
int or None; if set, forces the day of generated datetime.
force_hour
int or None; if set, forces the hour of generated datetime.
force_minute
int or None; if set, forces the minute of generated datetime.
force_second
int or None; if set, forces the second of generated datetime.
force_microsecond
int or None; if set, forces the microsecond of generated datetime.

Custom fuzzy fields

Alternate fuzzy fields may be defined. They should inherit from the BaseFuzzyAttribute class, and override its fuzz() method.

class factory.fuzzy.BaseFuzzyAttribute

Base class for all fuzzy attributes.

fuzz(self)
The method responsible for generating random values. Must be overridden in subclasses.

Managing randomness

Using random in factories allows to "fuzz" a program efficiently. However, it's sometimes required to reproduce a failing test.

factory.fuzzy uses a separate instance of random.Random, and provides a few helpers for this:

factory.fuzzy.get_random_state()
Call get_random_state() to retrieve the random generator's current state.
factory.fuzzy.set_random_state(state)
Use set_random_state() to set a custom state into the random generator (fetched from get_random_state() in a previous run, for instance)
factory.fuzzy.reseed_random(seed)
The reseed_random() function allows to load a chosen seed into the random generator.

Custom BaseFuzzyAttribute subclasses SHOULD use factory.fuzzy._random as a randomness source; this ensures that data they generate can be regenerated using the simple state from get_random_state().

Examples

Here are some real-world examples of using FactoryBoy.

Objects

First, let's define a couple of objects:

class Account(object):
    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __str__(self):
        return '%s (%s)' % (self.username, self.email)


class Profile(object):

    GENDER_MALE = 'm'
    GENDER_FEMALE = 'f'
    GENDER_UNKNOWN = 'u'  # If the user refused to give it

    def __init__(self, account, gender, firstname, lastname, planet='Earth'):
        self.account = account
        self.gender = gender
        self.firstname = firstname
        self.lastname = lastname
        self.planet = planet

    def __unicode__(self):
        return u'%s %s (%s)' % (
            unicode(self.firstname),
            unicode(self.lastname),
            unicode(self.account.accountname),
        )

Factories

And now, we'll define the related factories:

import datetime
import factory
import random

from . import objects


class AccountFactory(factory.Factory):
    class Meta:
        model = objects.Account

    username = factory.Sequence(lambda n: 'john%s' % n)
    email = factory.LazyAttribute(lambda o: '%s@example.org' % o.username)
    date_joined = factory.LazyFunction(datetime.datetime.now)


class ProfileFactory(factory.Factory):
    class Meta:
        model = objects.Profile

    account = factory.SubFactory(AccountFactory)
    gender = factory.Iterator([objects.Profile.GENDER_MALE, objects.Profile.GENDER_FEMALE])
    firstname = u'John'
    lastname = u'Doe'

We have now defined basic factories for our Account and Profile classes.

If we commonly use a specific variant of our objects, we can refine a factory accordingly:

class FemaleProfileFactory(ProfileFactory):
    gender = objects.Profile.GENDER_FEMALE
    firstname = u'Jane'
    user__username = factory.Sequence(lambda n: 'jane%s' % n)

Using the factories

We can now use our factories, for tests:

import unittest

from . import business_logic
from . import factories
from . import objects


class MyTestCase(unittest.TestCase):

    def test_send_mail(self):
        account = factories.AccountFactory()
        email = business_logic.prepare_email(account, subject='Foo', text='Bar')

        self.assertEqual(email.to, account.email)

    def test_get_profile_stats(self):
        profiles = []

        profiles.extend(factories.ProfileFactory.create_batch(4))
        profiles.extend(factories.FemaleProfileFactory.create_batch(2))
        profiles.extend(factories.ProfileFactory.create_batch(2, planet="Tatooine"))

        stats = business_logic.profile_stats(profiles)
        self.assertEqual({'Earth': 6, 'Mars': 2}, stats.planets)
        self.assertLess(stats.genders[objects.Profile.GENDER_FEMALE], 2)

Or for fixtures:

from . import factories

def make_objects():
    factories.ProfileFactory.create_batch(size=50)

    # Let's create a few, known objects.
    factories.ProfileFactory(
        gender=objects.Profile.GENDER_MALE,
        firstname='Luke',
        lastname='Skywalker',
        planet='Tatooine',
    )

    factories.ProfileFactory(
        gender=objects.Profile.GENDER_FEMALE,
        firstname='Leia',
        lastname='Organa',
        planet='Alderaan',
    )

Internals

ChangeLog

2.7.0 (2016-04-19)

New:

·
issue #267: Add factory.LazyFunction to remove unneeded lambada parameters, thanks to Hervé Cauwelier.
·
issue #251: Add parameterized factories and traits
·
issue #256, issue #292: Improve error messages in corner cases

Removed:

·
issue #278: Formally drop support for Python2.6

2.6.1 (2016-02-10)

New:

·
issue #262: Allow optional forced flush on SQLAlchemy, courtesy of Minjung.

2.6.0 (2015-10-20)

New:

·
Add factory.FactoryOptions.rename to help handle conflicting names (issue #206)
·
Add support for random-yet-realistic values through fake-factory, through the factory.Faker class.
·
factory.Iterator no longer begins iteration of its argument at import time, thus allowing to pass in a lazy iterator such as a Django queryset (i.e factory.Iterator(models.MyThingy.objects.all())).
·
Simplify imports for ORM layers, now available through a simple factory import, at factory.alchemy.SQLAlchemyModelFactory / factory.django.DjangoModelFactory / factory.mongoengine.MongoEngineFactory.

Bugfix:

·
issue #201: Properly handle custom Django managers when dealing with abstract Django models.
·
issue #212: Fix factory.django.mute_signals() to handle Django's signal caching
·
issue #228: Don't load django.apps.apps.get_model() until required
·
issue #219: Stop using mogo.model.Model.new(), deprecated 4 years ago.

2.5.2 (2015-04-21)

Bugfix:

·
Add support for Django 1.7/1.8
·
Add support for mongoengine>=0.9.0 / pymongo>=2.1

2.5.1 (2015-03-27)

Bugfix:

·
Respect custom managers in DjangoModelFactory (see issue #192)
·
Allow passing declarations (e.g Sequence) as parameters to FileField and ImageField.

2.5.0 (2015-03-26)

New:

·
Add support for getting/setting factory.fuzzy's random state (see issue #175, issue #185).
·
Support lazy evaluation of iterables in factory.fuzzy.FuzzyChoice (see issue #184).
·
Support non-default databases at the factory level (see issue #171)
·
Make factory.django.FileField and factory.django.ImageField non-post_generation, i.e normal fields also available in save() (see issue #141).

Bugfix:

·
Avoid issues when using factory.django.mute_signals() on a base factory class (see issue #183).
·
Fix limitations of factory.StubFactory, that can now use factory.SubFactory and co (see issue #131).

Deprecation:

·
Remove deprecated features from 2.4.0 (2014-06-21)
·
Remove the auto-magical sequence setup (based on the latest primary key value in the database) for Django and SQLAlchemy; this relates to issues issue #170, issue #153, issue #111, issue #103, issue #92, issue #78. See https://github.com/rbarrois/factory_boy… for technical details.

WARNING:

Version 2.5.0 removes the 'auto-magical sequence setup' bug-and-feature. This could trigger some bugs when tests expected a non-zero sequence reference.

Upgrading

WARNING:

Version 2.5.0 removes features that were marked as deprecated in v2.4.0.

All FACTORY_*-style attributes are now declared in a class Meta: section:

# Old-style, deprecated
class MyFactory(factory.Factory):
    FACTORY_FOR = models.MyModel
    FACTORY_HIDDEN_ARGS = ['a', 'b', 'c']

# New-style
class MyFactory(factory.Factory):
    class Meta:
        model = models.MyModel
        exclude = ['a', 'b', 'c']

A simple shell command to upgrade the code would be:

# sed -i: inplace update
# grep -l: only file names, not matching lines
sed -i 's/FACTORY_FOR =/class Meta:\n        model =/' $(grep -l FACTORY_FOR $(find . -name '*.py'))

This takes care of all FACTORY_FOR occurences; the files containing other attributes to rename can be found with grep -R FACTORY .

2.4.1 (2014-06-23)

Bugfix:

·
Fix overriding deeply inherited attributes (set in one factory, overridden in a subclass, used in a sub-sub-class).

2.4.0 (2014-06-21)

New:

·
Add support for factory.fuzzy.FuzzyInteger.step, thanks to ilya-pirogov (issue #120)
·
Add mute_signals() decorator to temporarily disable some signals, thanks to ilya-pirogov (issue #122)
·
Add FuzzyFloat (issue #124)
·
Declare target model and other non-declaration fields in a class Meta section.

Deprecation:

·

Use of FACTORY_FOR and other FACTORY class-level attributes is deprecated and will be removed in 2.5. Those attributes should now declared within the class Meta attribute:

For factory.Factory:

·
Rename FACTORY_FOR to model
·
Rename ABSTRACT_FACTORY to abstract
·
Rename FACTORY_STRATEGY to strategy
·
Rename FACTORY_ARG_PARAMETERS to inline_args
·
Rename FACTORY_HIDDEN_ARGS to exclude

For factory.django.DjangoModelFactory:
·
Rename FACTORY_DJANGO_GET_OR_CREATE to django_get_or_create

For factory.alchemy.SQLAlchemyModelFactory:
·
Rename FACTORY_SESSION to sqlalchemy_session

2.3.1 (2014-01-22)

Bugfix:

·
Fix badly written assert containing state-changing code, spotted by chsigi (issue #126)
·
Don't crash when handling objects whose __repr__ is non-pure-ascii bytes on Py2, discovered by mbertheau (issue #123) and strycore (issue #127)

2.3.0 (2013-12-25)

New:

·
Add FuzzyText, thanks to jdufresne (issue #97)
·
Add FuzzyDecimal, thanks to thedrow (issue #94)
·
Add support for EmbeddedDocument, thanks to imiric (issue #100)

2.2.1 (2013-09-24)

Bugfix:

·
Fixed sequence counter for DjangoModelFactory when a factory inherits from another factory relating to an abstract model.

2.2.0 (2013-09-24)

Bugfix:

·
Removed duplicated SQLAlchemyModelFactory lurking in factory (issue #83)
·
Properly handle sequences within object inheritance chains. If FactoryA inherits from FactoryB, and their associated classes share the same link, sequence counters will be shared (issue #93)
·
Properly handle nested SubFactory overrides

New:

·
The DjangoModelFactory now supports the FACTORY_FOR = 'myapp.MyModel' syntax, making it easier to shove all factories in a single module (issue #66).
·
Add factory.debug() helper for easier backtrace analysis
·
Adding factory support for mongoengine with MongoEngineFactory.

2.1.2 (2013-08-14)

New:

·
The ABSTRACT_FACTORY keyword is now optional, and automatically set to True if neither the Factory subclass nor its parent declare the FACTORY_FOR attribute (issue #74)

2.1.1 (2013-07-02)

Bugfix:

·
Properly retrieve the color keyword argument passed to ImageField

2.1.0 (2013-06-26)

New:

·
Add FuzzyDate thanks to saulshanabrook
·
Add FuzzyDateTime and FuzzyNaiveDateTime.
·
Add a factory_parent attribute to the LazyStub passed to LazyAttribute, in order to access fields defined in wrapping factories.
·
Move DjangoModelFactory and MogoFactory to their own modules (factory.django and factory.mogo)
·
Add the reset_sequence() classmethod to Factory to ease resetting the sequence counter for a given factory.
·
Add debug messages to factory logger.
·
Add a reset() method to Iterator (issue #63)
·
Add support for the SQLAlchemy ORM through SQLAlchemyModelFactory (issue #64, thanks to Romain Commandé)
·
Add factory.django.FileField and factory.django.ImageField hooks for related Django model fields (issue #52)

Bugfix

·
Properly handle non-integer pks in DjangoModelFactory (issue #57).
·
Disable RelatedFactory generation when a specific value was passed (issue #62, thanks to Gabe Koscky)

Deprecation:

·
Rename RelatedFactory's name argument to factory_related_name (See issue #58)

2.0.2 (2013-04-16)

New:

·
When FACTORY_DJANGO_GET_OR_CREATE is empty, use Model.objects.create() instead of Model.objects.get_or_create.

2.0.1 (2013-04-16)

New:

·
Don't push defaults to get_or_create when FACTORY_DJANGO_GET_OR_CREATE is not set.

2.0.0 (2013-04-15)

New:

·
Allow overriding the base factory class for make_factory() and friends.
·
Add support for Python3 (Thanks to kmike and nkryptic)
·
The default type for Sequence is now int
·
Fields listed in FACTORY_HIDDEN_ARGS won't be passed to the associated class' constructor
·
Add support for get_or_create in DjangoModelFactory, through FACTORY_DJANGO_GET_OR_CREATE.
·
Add support for fuzzy attribute definitions.
·
The Sequence counter can be overridden when calling a generating function
·
Add Dict and List declarations (Closes issue #18).

Removed:

·
Remove associated class discovery
·
Remove InfiniteIterator and infinite_iterator()
·
Remove CircularSubFactory
·
Remove extract_prefix kwarg to post-generation hooks.
·
Stop defaulting to Django's Foo.objects.create() when "creating" instances
·
Remove STRATEGY_*
·
Remove set_building_function() / set_creation_function()

1.3.0 (2013-03-11)

WARNING:

This version deprecates many magic or unexplicit features that will be removed in v2.0.0.

Please read the Upgrading section, then run your tests with python -W default to see all remaining warnings.

New

·
Global:
·
Rewrite the whole documentation
·
Provide a dedicated MogoFactory subclass of Factory
·
The Factory class:
·
Better creation/building customization hooks at factory.Factory._build() and factory.Factory.create()
·
Add support for passing non-kwarg parameters to a Factory wrapped class through FACTORY_ARG_PARAMETERS.
·
Keep the FACTORY_FOR attribute in Factory classes
·
Declarations:
·
Allow SubFactory to solve circular dependencies between factories
·
Enhance SelfAttribute to handle "container" attribute fetching
·
Add a getter to Iterator declarations
·
A Iterator may be prevented from cycling by setting its cycle argument to False
·
Allow overriding default arguments in a PostGenerationMethodCall when generating an instance of the factory
·
An object created by a DjangoModelFactory will be saved again after PostGeneration hooks execution

Pending deprecation

The following features have been deprecated and will be removed in an upcoming release.

·
Declarations:
·
InfiniteIterator is deprecated in favor of Iterator
·
CircularSubFactory is deprecated in favor of SubFactory
·
The extract_prefix argument to post_generation() is now deprecated
·
Factory:
·
Usage of set_creation_function() and set_building_function() are now deprecated
·
Implicit associated class discovery is no longer supported, you must set the FACTORY_FOR attribute on all Factory subclasses

Upgrading

This version deprecates a few magic or undocumented features. All warnings will turn into errors starting from v2.0.0.

In order to upgrade client code, apply the following rules:

·
Add a FACTORY_FOR attribute pointing to the target class to each Factory, instead of relying on automagic associated class discovery
·
When using factory_boy for Django models, have each factory inherit from DjangoModelFactory
·
Replace factory.CircularSubFactory('some.module', 'Symbol') with factory.SubFactory('some.module.Symbol')
·
Replace factory.InfiniteIterator(iterable) with factory.Iterator(iterable)
·
Replace @factory.post_generation() with @factory.post_generation
·
Replace factory.set_building_function(SomeFactory, building_function) with an override of the _build() method of SomeFactory
·
Replace factory.set_creation_function(SomeFactory, creation_function) with an override of the _create() method of SomeFactory

1.2.0 (2012-09-08)

New:

·
Add CircularSubFactory to solve circular dependencies between factories

1.1.5 (2012-07-09)

Bugfix:

·
Fix PostGenerationDeclaration and derived classes.

1.1.4 (2012-06-19)

New:

·
Add use_strategy() decorator to override a Factory's default strategy
·
Improve test running (tox, python2.6/2.7)
·
Introduce PostGeneration and RelatedFactory

1.1.3 (2012-03-09)

Bugfix:

·
Fix packaging rules

1.1.2 (2012-02-25)

New:

·
Add Iterator and InfiniteIterator for Factory attribute declarations.
·
Provide generate() and simple_generate(), that allow specifying the instantiation strategy directly. Also provides generate_batch() and simple_generate_batch().

1.1.1 (2012-02-24)

New:

·
Add build_batch(), create_batch() and stub_batch(), to instantiate factories in batch

1.1.0 (2012-02-24)

New:

·
Improve the SelfAttribute syntax to fetch sub-attributes using the foo.bar syntax;
·
Add ContainerAttribute to fetch attributes from the container of a SubFactory.
·
Provide the make_factory() helper: MyClassFactory = make_factory(MyClass, x=3, y=4)
·
Add build(), create(), stub() helpers

Bugfix:

·
Allow classmethod/staticmethod on factories

Deprecation:

·
Auto-discovery of FACTORY_FOR based on class name is now deprecated

1.0.4 (2011-12-21)

New:

·
Improve the algorithm for populating a Factory attributes dict
·
Add python setup.py test command to run the test suite
·
Allow custom build functions
·
Introduce MOGO_BUILD build function
·
Add support for inheriting from multiple Factory
·
Base Factory classes can now be declared abstract.
·
Provide DjangoModelFactory, whose Sequence counter starts at the next free database id
·
Introduce SelfAttribute, a shortcut for factory.LazyAttribute(lambda o: o.foo.bar.baz.

Bugfix:

·
Handle nested SubFactory
·
Share sequence counter between parent and subclasses
·
Fix SubFactory / Sequence interferences

1.0.2 (2011-05-16)

New:

·
Introduce SubFactory

1.0.1 (2011-05-13)

New:

·
Allow Factory inheritance
·
Improve handling of custom build/create functions

Bugfix:

·
Fix concurrency between LazyAttribute and Sequence

1.0.0 (2010-08-22)

New:

·
First version of factory_boy

Credits

·
Initial version by Mark Sandstrom (2010)
·
Developed by Raphaël Barrois since 2011

Ideas

This is a list of future features that may be incorporated into factory_boy:

·
When a Factory is built or created, pass the calling context throughout the calling chain instead of custom solutions everywhere
·
Define a proper set of rules for the support of third-party ORMs
·
Properly evaluate nested declarations (e.g factory.fuzzy.FuzzyDate(start_date=factory.SelfAttribute('since')))
·
genindex
·
modindex
·
search

Author

Raphaël Barrois, Mark Sandstrom

Info

Jul 19, 2016 2.7 Factory Boy