TvoroG / pytest-lazy-fixture

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

Lazy fixtures not working at all #33

Closed brian-barba-hernandez closed 5 years ago

brian-barba-hernandez commented 5 years ago

I had a few lazy fixtures loaded in some of my tests like this:

@pytest.mark.parametrize('user_group', [
        pytest.lazy_fixture('user_group_national_manager'),
        pytest.lazy_fixture('user_group_regional_manager'), 
        pytest.lazy_fixture('user_group_lwi_staff') 
    ])

Now, when the tests are being loaded it fails collecting them with:

/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py:258: in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
/usr/local/lib/python3.6/dist-packages/pluggy/manager.py:67: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
/usr/local/lib/python3.6/dist-packages/pluggy/manager.py:61: in <lambda>
    firstresult=hook.spec_opts.get('firstresult'),
/usr/local/lib/python3.6/dist-packages/_pytest/python.py:242: in pytest_pycollect_makeitem
    res = list(collector._genfunctions(name, obj))
/usr/local/lib/python3.6/dist-packages/_pytest/python.py:432: in _genfunctions
    self.ihook.pytest_generate_tests(metafunc=metafunc)
/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py:258: in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
/usr/local/lib/python3.6/dist-packages/pluggy/manager.py:67: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
/usr/local/lib/python3.6/dist-packages/pluggy/manager.py:61: in <lambda>
    firstresult=hook.spec_opts.get('firstresult'),
/usr/local/lib/python3.6/dist-packages/pytest_lazyfixture.py:70: in pytest_generate_tests
    normalize_metafunc_calls(metafunc, 'funcargs')
/usr/local/lib/python3.6/dist-packages/pytest_lazyfixture.py:77: in normalize_metafunc_calls
    calls = normalize_call(callspec, metafunc, valtype, used_keys)
/usr/local/lib/python3.6/dist-packages/pytest_lazyfixture.py:101: in normalize_call
    _, fixturenames_closure, arg2fixturedefs = fm.getfixtureclosure([val.name], metafunc.definition.parent)
E   ValueError: not enough values to unpack (expected 3, got 2)

If I changed the code to use tuples or arrays, the tests run but the lazy fixture is not loaded making the tests fail:

@pytest.mark.parametrize('user_group', [
        (pytest.lazy_fixture('user_group_national_manager'),),
        (pytest.lazy_fixture('user_group_regional_manager'),),
        (pytest.lazy_fixture('user_group_lwi_staff'),)
    ])
    assert response.status_code == 200
E   assert 403 == 200
E    +  where 403 = <HttpResponseForbidden status_code=403, "text/html">.status_code

This was working properly before the upgrade to 0.5.0

I tried to use the format specified in the README with no luck. I had to remove the lazy fixture and use a different approach in the meantime.

Any idea of what's broken?

FYI, each fixture just creates a Group and adds the user to the created group. I assert the groups the user belongs to and it belongs to none so the fixture is not loaded when the test runs.

YannickJadoul commented 5 years ago

@brian-barba-hernandez What version of pytest are you using? Maybe the tests failed to pick up an API change in between the 3.2.0 and the latest that are being tested?

YannickJadoul commented 5 years ago

The problem is this API change in pytest's FixtureManager: https://github.com/pytest-dev/pytest/commit/1dc5e97ac255b3a50b80b2a5400d7d467e952532#diff-6725679ae3a6464a250386ddaec4b18bR1150

I thought I'd looked up the version in which this was changed, and saw that it was the same version in which Metafunc got the definition attribute (https://github.com/pytest-dev/pytest/commit/180ae0920235e883138d56fa4274565793058465#diff-b33fa7b9ea0fc8ba664d4ca04002823aR740), but maybe I've missed something, there.

brian-barba-hernandez commented 5 years ago

@YannickJadoul These are the libs I'm using while testing:

platform linux -- Python 3.6.5, pytest-3.6.4, py-1.7.0, pluggy-0.7.1
Django settings: ***.settings.dev (from environment variable)
rootdir: /code, inifile: setup.cfg
plugins: timeout-1.3.3, lazy-fixture-0.5.0, django-3.4.4, cov-2.6.0, asyncio-0.9.0, celery-4.1.1
YannickJadoul commented 5 years ago

As a quick fix, updating pytest to 4.1.0 should work. But I'm looking into this, because this should also work!

YannickJadoul commented 5 years ago

Found it. The version numbers where not sorted correctly when I looked up the release of these two API changes. This should be correct:

$ git tag --contains 180ae0920235e883138d56fa4274565793058465 | sort -V
3.6.0
3.6.1
3.6.2
3.6.3
3.6.4
3.7.0
3.7.1
3.7.2
3.7.3
3.7.4
3.8.0
3.8.1
3.8.2
3.9.0
3.9.1
3.9.2
3.9.3
3.10.0
3.10.1
4.0.0
4.0.1
4.0.2
4.1.0
$ git tag --contains 1dc5e97ac255b3a50b80b2a5400d7d467e952532 | sort -V
3.7.0
3.7.1
3.7.2
3.7.3
3.7.4
3.8.0
3.8.1
3.8.2
3.9.0
3.9.1
3.9.2
3.9.3
3.10.0
3.10.1
4.0.0
4.0.1
4.0.2
4.1.0

And your version 3.6.4 contains one change, but not the other.

Apologies, I should've checked this better when I made that PR :-/ Should be fixed in #34, though (or by updating pytest to a version >= 3.7.0).

brian-barba-hernandez commented 5 years ago

@YannickJadoul Many thanks :)

TvoroG commented 5 years ago

Published new version 0.5.1 with fix from @YannickJadoul.

Thanks @brian-barba-hernandez for opening the issue!

brian-barba-hernandez commented 5 years ago

@TvoroG You're welcome, thanks for the fix!