smarie / python-pytest-cases

Separate test code from test cases in pytest.
https://smarie.github.io/python-pytest-cases/
BSD 3-Clause "New" or "Revised" License
348 stars 40 forks source link

pytest_cases.fixture unpack_into seems to invalidate scope argument #296

Open lucapton opened 1 year ago

lucapton commented 1 year ago

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.

smarie commented 1 year ago

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

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.

lucapton commented 1 year ago

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.

smarie commented 1 year ago

Very clear @lucapton , thanks! I'll see what I can do one of these days