Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_LazyValueCaseParamValue is injected instead of the case function result #274

Closed
smarie opened this issue May 20, 2022 · 2 comments · Fixed by #275
Closed

_LazyValueCaseParamValue is injected instead of the case function result #274

smarie opened this issue May 20, 2022 · 2 comments · Fixed by #275

Comments

@smarie
Copy link
Owner

smarie commented May 20, 2022

When at least two "basic" cases are present next to each other in a set of cases where there is at least a fixture case (parameterized case or case requiring a fixture), then the case function is not called and a _LazyValueCaseParamValue is wrongly injected.

Reproducible example:

import pytest
from pytest_cases import fixture, parametrize_with_cases

class DataCases:
    def data_dummy(self):
        return 1

    def data_dummy2(self):
        return 1

    @pytest.mark.parametrize("a", [False])
    def data_dummy3(self, a):
        return 1

@fixture
@parametrize_with_cases("dset", cases=DataCases, prefix="data_", debug=True)
def dataset(dset):
    assert dset == 1
    yield dset

def test_foo(dataset):
    pass

yields

============================= test session starts =============================
collecting ... Case function DataCases.data_dummy > 1 lazy_value() with id dummy and additional marks None
Case function DataCases.data_dummy2 > 1 lazy_value() with id dummy2 and additional marks None
Case function DataCases.data_dummy3 > Creating fixture 'dummy3' in <module 'test_case_fixture' from 'C:\\_dev\\python_ws\\_Libs_Schneider\\CIPP_docs\\tests\\test_case_fixture.py'>
Case function DataCases.data_dummy3 > fixture_ref('dummy3') with marks ()
Fixture references found. Creating references and fixtures...
 - Creating new fixture 'dataset_dset_is_P0toP1' to handle parameters 0 to 1
Creating parametrized fixture 'dataset_dset_is_P0toP1' returning [_LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None), _LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy2 at 0x00000164FDBCB488>, <test_case_fixture.DataCases object at 0x00000164FDD82748>), _id='dummy2', _marks=(), cached_value_context=None, cached_value=None)]
 - Creating reference to existing fixture 'dummy3'
Creating final union fixture 'dataset_dset' with alternatives ['dataset_dset_is_P0toP1', 'dummy3']
Creating final test function wrapper with signature dataset(dataset_dset)
collected 3 items

test_case_fixture.py::test_foo[dummy] ERROR
test setup failed
_LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None) != 1

Expected :1
Actual   :_LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None)
<Click to see difference>

dset = _LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None)

    @fixture
    @parametrize_with_cases("dset", cases=DataCases, prefix="data_", debug=True)
    def dataset(dset):
>       assert dset == 1
E       AssertionError: assert _LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None) == 1
E         +_LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x00000164FDBCB510>, <test_case_fixture.DataCases object at 0x00000164FDD82668>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None)
E         -1
@smarie
Copy link
Owner Author

smarie commented May 20, 2022

The bug does not happen when the cases are used to parametrize the test (not a fixture).
The following works:

import pytest
from pytest_cases import parametrize_with_cases

class DataCases:
    def data_dummy(self):
        return 1

    def data_dummy2(self):
        return 1

    @pytest.mark.parametrize("a", [False])
    def data_dummy3(self, a):
        return 1

@parametrize_with_cases("dset", cases=DataCases, prefix="data_", debug=True)
def test_foo(dset):
    assert dset == 1

@smarie
Copy link
Owner Author

smarie commented May 20, 2022

Decoding what happens in the original (failing) example:

  • @parametrize_with_cases creates the dummy3 fixture for case 3 and lazy_values for the first 2 cases and calls @parametrize
  • @parametrize creates the dataset_dset_is_P0toP1 fixture, parametrized with the first two lazy values
  • @parametrize creates the "union" fixture dataset_dset with alternatives ['dataset_dset_is_P0toP1', 'dummy3']
  • @parametrize creates a wrapper around def dataset(dset), that has the signature def dataset(dataset_dset). This is the function that will be decorated by @fixture (instead of the original function)

We can see this in the debug log enabled using debug = True :

Case function DataCases.data_dummy > 1 lazy_value() with id dummy and additional marks None
Case function DataCases.data_dummy2 > 1 lazy_value() with id dummy2 and additional marks None
Case function DataCases.data_dummy3 > Creating fixture 'dummy3' in <module 'tests.cases.issues.test_issue_274' from 'C:\\_dev\\python_ws\\_Libs_OpenSource\\python-pytest-cases\\tests\\cases\\issues\\test_issue_274.py'>
Case function DataCases.data_dummy3 > fixture_ref('dummy3') with marks ()
Fixture references found. Creating references and fixtures...
 - Creating new fixture 'dataset_dset_is_P0toP1' to handle parameters 0 to 1
Creating parametrized fixture 'dataset_dset_is_P0toP1' returning [_LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy at 0x000001F6C607BCA0>, <tests.cases.issues.test_issue_274.DataCases object at 0x000001F6C60815E0>), _id='dummy', _marks=(), cached_value_context=None, cached_value=None), _LazyValueCaseParamValue(valuegetter=functools.partial(<function DataCases.data_dummy2 at 0x000001F6C607BE50>, <tests.cases.issues.test_issue_274.DataCases object at 0x000001F6C6081D60>), _id='dummy2', _marks=(), cached_value_context=None, cached_value=None)]
 - Creating reference to existing fixture 'dummy3'
Creating final union fixture 'dataset_dset' with alternatives ['dataset_dset_is_P0toP1', 'dummy3']
Creating final test function wrapper with signature dataset(dataset_dset)

smarie pushed a commit that referenced this issue May 20, 2022
…resolved before being injected in a parametrized function, and was therefore appearing as a `_LazyValueCaseParamValue `. Fixed #274
smarie added a commit that referenced this issue May 20, 2022
…es are present in a @parametrize containing a fixture_ref (#275)

* Fixed issue where a lazy value (for example a case function) was not resolved before being injected in a parametrized function, and was therefore appearing as a `_LazyValueCaseParamValue `. Fixed #274

* 3.6.13 changelog

Co-authored-by: Sylvain MARIE <sylvain.marie@se.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant