python-pytest-cases
python-pytest-cases copied to clipboard
pytest_cases.fixture unpack_into seems to invalidate scope argument
The example below causes a ScopeMismatch error despite everything being session scoped.
import pytest
import pytest_cases
@pytest_cases.fixture(scope="session", unpack_into="a1, a2")
def a():
return None, None
@pytest.fixture(scope="session")
def b(a1):
return None
def test_b(b):
pass
results in:
============================= test session starts ==============================
collecting ... collected 1 item
test_unpack_into_bug.py::test_b ERROR [100%]
test setup failed
ScopeMismatch: You tried to access the function scoped fixture a1 with a session scoped request object, involved factories:
tests/test_unpack_into_bug.py:10: def b(a1)
<makefun-gen-11>:1: def a1(a, request)
========================= 4 warnings, 1 error in 0.44s =========================
Process finished with exit code 1
If you directly call pytest_cases.unpack_into("a1, a2", a) instead of the argument in pytest_cases.fixture, then there there is no issue as a1 and a2 are correctly scoped to session instead of function.
I'm getting these results using python 3.8.10, pytest 7.2.2, and pytest_cases 3.6.14 in an Ubuntu 20.04 docker container.
Good catch @lucapton ! Looking at the source code, this is...normal :(
This is because my current code in _unpack_fixture only reuses the original fixture's scope if the provided source fixture is a fixture symbol.
https://github.com/smarie/python-pytest-cases/blob/main/src/pytest_cases/fixture_core1_unions.py#L511
When it is a string it uses 'function' scope. It does not try to ask pytest's fixture manager for help.
But fixing this would anyway not help in your situation, since the fixture a is not created yet when _unpack_fixture is called:
https://github.com/smarie/python-pytest-cases/blob/main/src/pytest_cases/fixture_core2.py#L410
So as a workaround I suggest to
- modify
_unpack_fixtureto support an explicitscope: str = Noneargument, that would be used to override the scope explicitly when provided - modify
_decorate_fixture_plusso that the scope is actually explicitly passed to_unpack_fixturewhenunpack_intois non-none
Would you like to try this in a PR ? Otherwise, I'll do it one of these days, this seems fairly straightforward so that I can squeeze it into my agenda.
I'm not familiar with the inner workings of pytest nor pytest_cases, so I don't think I can afford the time to do the PR, as much as I'd like to.
I want to clarify that pytest_cases.unpack_into("a1, a2", a) is a perfect workaround for the desired result I wanted. Still, the fact that fixtures created through pytest_cases.fixture(scope=x, unpack_into="y, z") don't have scope x but instead always function tripped me up for a while so I wanted to share both the issue and the workaround.
Very clear @lucapton , thanks! I'll see what I can do one of these days