====== Factory Boy ======
===== Introduction =====
==== What is Factory Boy? ====
Factory Boy aim is to replace static and hard to maintain complex object fixtures (test data).
This is test data created with factory boy (We need a 200€, paid order, shipping to australia, for a VIP customer):
def test_with_factory_boy(self):
order = OrderFactory(
amount=200,
status='PAID',
customer__is_vip=True,
address__country='AU',
)
This is data created without factory boy:
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,
)
==== Installation ====
$ pip install factory_boy
==== ORMs ====
=== MongoEngine ===
from factory.mongoengine import MongoEngineFactory
# ...
class User(Document):
# ...
class UserFactory(MongoEngineFactory):
===== First steps =====
==== Factories ====
Factories declare a set of attributes for an object. The class of this object must be defined in the ''model'' attribute of a subclass ''Meta'' (:!: In previous versions the class ''Meta'' with its attribute ''model'' it is substituted by ''FACTORY_FOR'' attribute):
import factory
import models
class UserFactory(factory.Factory):
class Meta:
model = models.User
first_name = 'John'
last_name = 'Doe'
admin = False
From here we can:
# Build a not saved user
user = UserFactory.build()
# Build a saved user
user = UserFactory.create()
# Build a saved user
user = UserFactory()
# Returns a dict of attributes that can be used to build a user
attributes = UserFactory.attributes()
# Build a not saved user overriding its first_name
user = UserFactory.build(first_name='Joe')
# Build ten not saved users named Joe
users = USerFactory.build(10, first_name="Joe")
=== Derived values ===
We can create a field which is derived from others (this example will put ''joe.blow@example.com'' in email field):
class UserFactory(factory.Factory):
FACTORY_FOR = 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())
=== Unique values in sequence ===
We can create a field which is auto-incremented as:
class UserFactory(factory.Factory):
FACTORY_FOR = models.User
email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n))
=== Associate factories ===
We can associate a field with other factory to create other sub instance:
class PostFactory(factory.Factory):
FACTORY_FOR = models.Post
author = factory.SubFactory(UserFactory)