pytest-factoryboy
pytest-factoryboy copied to clipboard
Problems with Maybe / Trait when defined in Params
Especially with FactoryBoy 3.2. See failing tests in https://github.com/pytest-dev/pytest-factoryboy/pull/125
I'm still facing this issue:
AttributeError: 'Maybe' object has no attribute 'call'
request = <SubRequest 'timesheet' for <Function test_can_include_date>>
def deferred(request):
> declaration.call(instance, step, context)
E AttributeError: 'Maybe' object has no attribute 'call'
../.venv/lib/python3.9/site-packages/pytest_factoryboy/fixture.py:294: AttributeError
Debugging info:
(Pdb) declaration
Maybe(<SelfAttribute('has_entries', default=False)>, yes=<factory.declarations.RelatedFactoryList object at 0x7ffb03b409d0>, no=<factory.declarations.Skip object at 0x7ffb23dcc160>)
(Pdb) type(step)
<class 'factory.builder.BuildStep'>
(Pdb) context
PostGenerationContext(value_provided=True, value=Maybe(<SelfAttribute('has_entries', default=False)>, yes=<factory.declarations.RelatedFactoryList object at 0x7ffb03b409d0>, no=<factory.declarations.Skip object at 0x7ffb23dcc160>), extra={})
Versions in my environment:
factory-boy==3.2.0
pytest==6.2.5
pytest-django==4.4.0
pytest-factoryboy==2.1.0
I also encountered the same event.
The factory I defined is the one that contains the RelatedFactory in the Trait.
as follows:
import factory
class UserFactory(factory.Factory):
class Meta:
model = User
id = 1
class BookFactory(factory.Factory):
class Meta:
model = Book
class Params:
user_r = factory.Trait(
users=factory.RelatedFactoryList("factories.UserFactory"),
factory_related_name="id",
size=10,
)
name = "book name"
I am not sure about the details of the implementation, but it worked locally by modifying the conditional expression for the decl object in the following location.
https://github.com/pytest-dev/pytest-factoryboy/blob/78844d9f7b97047b94348066933f73f75854839c/pytest_factoryboy/fixture.py#L403
if isinstance(decl, (factory.RelatedFactory, factory.Maybe)):
If the corrections above are sufficient to address the issue, then please fix it!
It's really hard to properly handle Maybe
(and also Trait
because under the hood it uses as_declarations
to override affected fields with Maybe
- reference).
To properly generate fixtures for Maybe
we need to somehow generate a proper dependencies chain, which is really hard, because Maybe.decider
can be computed from anything using some declaration, however, the most commonly used are probably the following ones:
-
SimpleParameter
(in the case ofTrait
) -
SelfAttribute
-
LazyAttribute
Maybe
s can be also nested, which makes implementation even more complicated.
If you have any idea how to add support for Maybe
and/or Params
to our code, please share it here!