python-pytest-cases icon indicating copy to clipboard operation
python-pytest-cases copied to clipboard

pytest_cases.fixture unpack_into seems to invalidate scope argument

Open lucapton opened this issue 2 years ago • 3 comments
trafficstars

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.

lucapton avatar Mar 13 '23 13:03 lucapton

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_fixture to support an explicit scope: str = None argument, that would be used to override the scope explicitly when provided
  • modify _decorate_fixture_plus so that the scope is actually explicitly passed to _unpack_fixture when unpack_into is 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.

smarie avatar Mar 13 '23 14:03 smarie

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.

lucapton avatar Mar 13 '23 15:03 lucapton

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

smarie avatar Mar 17 '23 08:03 smarie