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 Common 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: user0>
   >>> UserFactory()
   <User: user1>

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.
