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, )
$ pip install factory_boy
from factory.mongoengine import MongoEngineFactory # ... class User(Document): # ... class UserFactory(MongoEngineFactory):
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")
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())
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))
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)