FactoryBoy / factory_boy

A test fixtures replacement for Python
https://factoryboy.readthedocs.io/
MIT License
3.49k stars 392 forks source link

Support for SQLAlchemy Core ( without ORM )? #133

Closed faliev closed 10 years ago

faliev commented 10 years ago

Is it possible to implement? If so, would you please tell me where to start?

hartror commented 10 years ago

You might be able to do it with your own base factory. Certainly the code in https://github.com/rbarrois/factory_boy/blob/master/factory/alchemy.py isn't complex however there are likely assumptions elsewhere in factory boy about interacting in an ORM style rather than Core's style of doing things.

faliev commented 10 years ago

Thank you. We ended up hacking it up to add support for core way of doing things. It's tough to submit a patch at this point, but I'll try to do it in the future once we settle on implementation.

m-aciek commented 6 years ago

@faliev Just for the record, did you succeed?

pablobcb commented 4 years ago

it would be great an example on how using it with table definitions instead of classes

havok2063 commented 3 years ago

@faliev Did you end up implementing this? If so, could you provide some examples?

rbarrois commented 3 years ago

@havok2063 I'll try to provide an example!

Assuming your table is defined like this:

users = Table('users', metadata,
   Column('id', Integer, Sequence('user_id_seq'), primary_key=True),
   Column('name', String(50)),
   Column('fullname', String(50)),
   Column('nickname', String(50))
)

Then your factory could look like this:

from myapp import get_connection  # To get your "engine.connection" class

class SQLAlchemyCoreFactory(factory.Factory):
    class Meta:
        abstract = True

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        connection = get_connection()
        result = connection.execute(model_class.insert().values(**kwargs))
        return result.inserted_primary_key

class UserFactory(SQLAlchemyCoreFactory):
    class Meta:
        model = users

    name = factory.Faker("name")
    fullname = factory.Faker("name")
    nickname = factory.Faker("first_name")

>>> UserFactory()
42
havok2063 commented 3 years ago

Thanks @rbarrois this is helpful indeed. It's a good starting point. I was hoping for something that also enabled use of build and create but that might be too tied with the ORM version. It's probably adaptable though with some work. Now I just need to figure out to mock my functions and object methods that use sqla core to use an engine that can rollback inserts, and combine it with this. It seems that factory boy only handles the creation and insertion of objects.

rbarrois commented 3 years ago

@havok2063 for a build vs. create you could simply have the _build() return the dict of values ;)

havok2063 commented 3 years ago

@rbarrois Yeah good point. :)