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 :doc:`recipes`,
          while those needing detailed documentation will be interested in the :doc:`reference` section.


Basic usage
-----------


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

- Subclass ``factory.Factory`` (or a more suitable subclass)
- Set its ``FACTORY_FOR`` attribute to the target class
- Add defaults for keyword args to pass to the associated class' ``__init__`` method


.. code-block:: python

    import factory
    from . import base

    class UserFactory(factory.Factory):
        FACTORY_FOR = base.User

        firstname = "John"
        lastname = "Doe"

You may now get ``base.User`` instances trivially:

.. code-block:: pycon

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

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

.. code-block:: pycon

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


A given class may be associated to many :class:`~factory.Factory` subclasses:

.. code-block:: python

    class EnglishUserFactory(factory.Factory):
        FACTORY_FOR = base.User

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


    class FrenchUserFactory(factory.Factory):
        FACTORY_FOR = base.User

        firstname = "Jean"
        lastname = "Dupont"
        lang = 'fr'


.. code-block:: pycon

    >>> 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 :class:`~factory.Sequence` declaration:

.. code-block:: python

    class UserFactory(factory.Factory):
        FACTORY_FOR = models.User

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

.. code-block:: pycon

    >>> UserFactory()
    <User: user1>
    >>> UserFactory()
    <User: user2>

.. note:: For more complex situations, you may also use the :meth:`~factory.@sequence` decorator:

          .. code-block:: python

            class UserFactory(factory.Factory):
                FACTORY_FOR = models.User

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


LazyAttribute
-------------

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

.. code-block:: python

    class UserFactory(factory.Factory):
        FACTORY_FOR = models.User

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

.. code-block:: pycon

    >>> 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 :class:`~factory.Sequence`, a :meth:`~factory.@lazy_attribute` decorator is available.


Inheritance
-----------


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

The subclassed :class:`~factory.Factory` will inherit all declarations from its parent,
and update them with its own declarations:

.. code-block:: python

    class UserFactory(factory.Factory):
        FACTORY_FOR = base.User

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

    class AdminFactory(UserFactory):
        admin = True
        group = 'admins'

.. code-block:: pycon

    >>> 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:

.. code-block:: pycon

    >>> 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 :data:`~factory.Factory.FACTORY_ARG_PARAMETERS` attribute:

.. code-block:: python

    class MyFactory(factory.Factory):
        FACTORY_FOR = MyClass
        FACTORY_ARG_PARAMETERS = ('x', 'y')

        x = 1
        y = 2
        z = 3

.. code-block:: pycon

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


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, :meth:`factory.Factory.create` simply calls ``AssociatedClass(**kwargs)``.
          You should use :class:`~factory.DjangoModelFactory` for Django models.


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


Calling a :class:`~factory.Factory` subclass will provide an object through the default strategy:

.. code-block:: python

    class MyFactory(factory.Factory):
        FACTORY_FOR = MyClass

.. code-block:: pycon

    >>> MyFactory.create()
    <MyFactory: X (saved)>

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

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


The default strategy can ba changed by setting the class-level :attr:`~factory.Factory.FACTROY_STRATEGY` attribute.


