Avoiding duplicates with factory_boy factories

Related searches

I'm using factory_boy to create test fixtures. I've got two simple factories, backed by SQLAlchemy models (simplified below).

I'd like to be able to call AddressFactory.create() multiple times, and have it create a Country if it doesn't already exist, otherwise I want it to re-use the existing record.

class CountryFactory(factory.Factory):
    FACTORY_FOR = Country

    cc = "US"
    name = "United States"


class AddressFactory(factory.Factory):
    FACTORY_FOR = Address

    name = "Joe User"
    city = "Seven Mile Beach"
    country = factory.SubFactory(CountryFactory, cc="KY", name="Cayman Islands")

My question is: how can I set up these factories so that factory_boy doesn't try to create a new Country every time it creates an Address?

In the latest factory-boy==2.3.1 you can add FACTORY_DJANGO_GET_OR_CREATE

class CountryFactory(factory.django.DjangoModelFactory):
    FACTORY_FOR = 'appname.Country'
    FACTORY_DJANGO_GET_OR_CREATE = ('cc',)

    cc = "US"
    name = "United States"

Assuming cc field is the unique identifier.

Common recipes — Factory Boy latest documentation, ForeignKey(Group) # factories.py import factory from . import models class evaluated until the first call to UserFactory ; thus avoiding DB queries at import time. Hi all, I upgraded to factory_boy 2.9.1 and a bunch of my tests are failing. I've isolated it down to a simple set of models. This was modeled on the documentation. import factory from django.db import models from django.contrib.auth.mod

While you're right that there's no get_or_create function for SQLAlchemy-based factories, if the objects you want to use as a foreign key already exist, you can iterate through them:

http://factoryboy.readthedocs.org/en/latest/recipes.html#choosing-from-a-populated-table

So conceivably you could hack together a solution in your factory by using a lazy attribute that first checks if the object exists in the db, and if so it uses this method to iterate through them, but if the object doesn't exist, it calls a SubFactory to create the object first.

factory_boy — Factory Boy latest documentation, Factories declare a set of attributes used to instantiate a Python object. The class of To avoid running mongoengine tests (e.g no mongo server installed), run:. factory_boy is a fixtures replacement based on thoughtbot's factory_bot <https: hard to maintain fixtures with easy-to-use factories for complex object.

Another hacky solution is to overwrite the create method of the factory in a way that the object is searched by a querying and caching the results.

This simple example does no filtering on the **kwargs though:

class StaticFactory(SQLAlchemyModelFactory):                        

    counter = 0                                                     
    cache = []                                                      
    model = None                                                    

    @classmethod                                                    
    def create(cls, **kwargs):                                      
        if not cls.cache:                                           
            cls.cache = your_session.query(cls.model).all()     
        instance = cls.cache[cls.counter]                           
        cls.counter = (cls.counter + 1) % len(cls.cache)            
        return instance                                             

New version of factory_boy does not work with a simple , Hi all, I upgraded to factory_boy 2.9.1 and a bunch of my tests are failing. This was modeled on the documentation. import factory from django.db pass in None to prevent UserFactory from creating another # profile (this disables the errorvalue IntegrityError: (1062, "Duplicate entry '1' for key 'user_id'")� factory_boy is a fixtures replacement based on thoughtbot’s factory_bot.. As a fixtures replacement tool, it aims to replace static, hard to maintain fixtures with easy-to-use factories for complex objects.

For SqlAlchemy you can try this. This is cahce factory as well:

class StaticFactory(factory.alchemy.SQLAlchemyModelFactory):):
    __static_exclude = ('__static_exclude', '__static_cache',)
    __static_cache = {}

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        """Helper for avoid duplicate factory"""

        # Exclude static cache
        cls._meta.exclude += cls.__static_exclude

        _unique_key = None

        # Get first unique keys from table. I'll be cache key.
        for col in model_class.__table__.columns:
            if any([col.primary_key, col.unique]):
                _unique_key = kwargs.get(col.name)
                if _unique_key:
                    break

        _instance = cls.__static_cache.get(_unique_key)
        if _instance:
            return _instance

        _session = cls._meta.sqlalchemy_session
        with _session.no_autoflush:
            obj = model_class(*args, **kwargs)
            _session.add(obj)
            cls.__static_cache.update({_unique_key: obj})
            return obj

class LanguageFactory(StaticFactory):
    class Meta:
        model = Language
        exclude = ('lang',)

FactoryBoy/factory_boy, For any duplicate FuzzyAttributes that are more powerful than their Faker equivalents, where in that case or resort to creating your own in order to avoid using any fuzzy attributes? Can Factory Boy be improved to support such a use case? factory_boy. factory_boy is a fixtures replacement based on thoughtbot's factory_bot. As a fixtures replacement tool, it aims to replace static, hard to maintain fixtures with easy-to-use factories for complex objects.

We can create a new instance of address with already existing country instance using factory.Iterator method

import factory, factory.django
from . import models


class CountryFactory(factory.Factory.DjangoModelFactory):
    model = models.Country

    cc = "US"
    name = "United States"

class AddressFactory(factory.Factory.DjangoModelFactory):
    model = models.Address

    name = "Joe User"
    city = "Seven Mile Beach"
    country = factory.Iterator(models.Country.objects.all())

Here, we accessed Country instances from the database and passed it to the country attribute of AddressFactory, which creates an address instance with already created country instance in database.

Handling unique constraints with factory boy, duplicate key value violates unique constraint "app_group_name_key" DETAIL: Key (name)=('ADMIN') already exists. In our example, creating� FactoryBoy / factory_boy. Watch 42 Star 2.2k Mentioning django-factory_boy Factories in the documentation duplicate key value violates unique constraint pkey

Trudeau government awards Quebec company with no Canadian factories 10-year $133 MILLION PPE deal A Quebec company has landed a $133,486,868 sole-sourced federal deal to manufacture pandemic masks despite not having a factory in Canada

High performing factories are given public recognition to acknowledge their achievement. These factories will be presented as industry leader in sustainable compliance. BUYER PORTAL High-performing factories will be highlighted in the Buyer Portal with a description of the criteria and how they met them.

factory_bot . factory_bot is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.

Comments
  • Did you take a look at factory.alchemy?
  • Not sure what you're referring to in that link; there's nothing in that specific file that seems helpful. I've looked at the docs for factory_boy and the SQLAlchemy factory in particular, but I haven't seen anything about re-using records. Basically looking for a "find or create" type functionality.
  • After more research into this, the short answer is that you can't do it. There's support for get-or-create with Django models, but not SQLAlchemy. I'm leaving this question open because I'm hoping to add SQLAlchemy support for this one of these days if no one beats me to it.
  • As I mentioned in my question and followup comment above, I'm using SQLAlchemy. I know this exists for Django, but that doesn't help me. The functionality I'm looking for doesn't exist in factory boy, and I still haven't had the time to add it myself.
  • Doesn't work in factory_boy==2.10.0 (not sure if this applies to SQLAlchemy or not)
  • now django_get_or_create as of 2.4.0 factoryboy.readthedocs.io/en/latest/…
  • This is definitely a hacky solution, much better if you submitted a PR adding the get_or_create ability for SQLAlchemy ;-)