TvoroG / pytest-lazy-fixture

It helps to use fixtures in pytest.mark.parametrize
MIT License
379 stars 30 forks source link

pytest-lazy-fixture breaks with Traits in factoryboy 3.2.0: 'Maybe' object has no attribute 'call' #52

Open radekwlsk opened 3 years ago

radekwlsk commented 3 years ago

After updating factoryboy to 3.2.0 my tests using lazy_fixture with fixtures that use Trait (in result using Maybe) raise AttributeError: 'Maybe' object has no attribute 'call'.

python_version = "3.8"
django = "~=3.0"
factory-boy = "~=3.2.0"
pytest = "~=5.4.3"
pytest-factoryboy = "~=2.1.0"
pytest-lazy-fixture = "~=0.6.3"

Attached is a full traceback from failed test case.

request = <FixtureRequest for <Function test_success>>

    def fill(request):
        item = request._pyfuncitem
        fixturenames = getattr(item, "fixturenames", None)
        if fixturenames is None:
            fixturenames = request.fixturenames

        if hasattr(item, 'callspec'):
            for param, val in sorted_by_dependency(item.callspec.params, fixturenames):
                if val is not None and is_lazy_fixture(val):
                    item.callspec.params[param] = request.getfixturevalue(val.name)
                elif param not in item.funcargs:
                    item.funcargs[param] = request.getfixturevalue(param)

>       _fillfixtures()

/home/django/venv/lib/python3.8/site-packages/pytest_lazyfixture.py:39: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/django/venv/lib/python3.8/site-packages/pytest_factoryboy/fixture.py:188: in model_fixture
    factoryboy_request.evaluate(request)
/home/django/venv/lib/python3.8/site-packages/pytest_factoryboy/plugin.py:83: in evaluate
    self.execute(request, function, deferred)
/home/django/venv/lib/python3.8/site-packages/pytest_factoryboy/plugin.py:65: in execute
    self.results[model][attr] = function(request)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <SubRequest 'user' for <Function test_success>>

    def deferred(request):
>       declaration.call(instance, step, context)
E       AttributeError: 'Maybe' object has no attribute 'call'

/home/django/venv/lib/python3.8/site-packages/pytest_factoryboy/fixture.py:294: AttributeError

Seems like it could be a problem in pytest_factoryboy itself but I've seen it raised only for tests using lazy_fixture.

TvoroG commented 3 years ago

Hey! Can you show minimal example of broken test?

Thanks for opening the issue!

MRigal commented 3 years ago

The problem comes from this code change: https://github.com/FactoryBoy/factory_boy/pull/828/files#diff-92a7290251f0a9a1c6f4309e8a63df0920e00a52cbf1257aa1ee62bbc11da044L497

MRigal commented 3 years ago

The problem doens't come frompytest-lazy-fixture but from pytest-factoryboy, see this PR for failing tests https://github.com/pytest-dev/pytest-factoryboy/pull/125

Update: It looks like it comes from pytest-lazy-fixture because the plugin is calling the _fillfixtures method/fixture first. So it is triggering the behaviour which would happen else a bit later anyway

I think @TvoroG you can close this issue (and if you want help to fix the issue on the pytest-factoryboy side)