====== 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)