FactoryBoy / factory_boy

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

Add an API to get all accepted factory attributes #312

Open ekohl opened 8 years ago

ekohl commented 8 years ago

This comes from https://github.com/pytest-dev/pytest-factoryboy/issues/23.

What pytest-factoryboy does is convert all declarations to pytest fixtures allowing them to be easily overridden and parameterized. Currently is uses .declarations() (https://github.com/pytest-dev/pytest-factoryboy/blob/9ab025bb4a91c52daa671bfdea12d15cc7e3a2d8/pytest_factoryboy/fixture.py#L62) but that only works for explicitly overridden declarations. On a DjangoModelFactory there are also the model attributes that are accepted and I assume something similar works for the SQLAlchemy factory.

What i propose is a function (accepted_attributes()?) that lists all attributes that it can accept. For simple factories it will be equal to declarations(), but for a DjangoModelFactory it will also include all model fields.

rbarrois commented 8 years ago

@ekohl that's an interesting idea!

In order to add this, we'd first need to add some model introspection code — probably based on some of the code in the auto_factory branch.

Would you be interested in building this? I'd be happy to guide you through the code and ideas :-)

ekohl commented 8 years ago

I'd certainly be interested, but I'm suffering from a lack of time I can't promise anything. The AutoFactory sounds like a nice idea btw!

rbarrois commented 8 years ago

@ekohl no problem, that's the curse of open-source anyway ;)

Don't hesitate to ping me repeatedly if you're ready to work on this and I'm not responding!

ekohl commented 8 years ago

Will do

asteinlein commented 8 years ago

Came across this myself when looking at integrating factoryboy + pytest-factoryboy, for our SQLAlchemy models. I'd love this as well.

ekohl commented 8 years ago

@rbarrois https://github.com/ekohl/factory_boy/commit/00deff0be4bfd24c47b8cffe9741738f953350db is my first stab at this. It's very raw and I know not everything is in the right place so I'd appreciate being pointed in the right direction :)

I did notice that get_field_names will error out on the OneToOne field because it doesn't have the blank attribute so you probably want to look at null there.

ekohl commented 8 years ago

@rbarrois ping

rbarrois commented 8 years ago

@ekohl the design looks nice; but I'll have to spend some more time on that old branch to put everything back in memory ;)

And indeed, your point about field.blank is spot-on: blank handles forms, but we're interested in the DB-side model!

In my experience, one of the most complex parts of factory_boy's internals is handling class inheritance, since:

Have you tried it on such cases? A good place to look would be to add tests for accepted_attributes in the batch around https://github.com/rbarrois/factory_boy/blob/master/tests/test_using.py#L795,L942 :)

olegpidsadnyi commented 6 years ago

@rbarrois I'm currently working on compatibility of the pytest-factoryboy with the newest pytest and the newest factoryboy (2.10.0). I'm not using deprecated "attributes" or "declarations" anymore.

Please feel free to remove those.

P.S. I'm having a hard time with the new underlying data structures like builder and step, declaration set and the contexts. Especially because I need to be able to instantiate a model without post_declarations being executed. I can't afford running some of the post_declarations for each model because they may create cyclic dependencies, so I'm deferring those. If the build() workflow would be more split that would be a great help. https://github.com/pytest-dev/pytest-factoryboy/pull/57/files#diff-aaf8ccc99345bc1dd35fd77d24657d8cR202