python-pytest-cases
python-pytest-cases copied to clipboard
[Major] Improve the fixture union engine to support hybrid param+fixture mode
The latest developments about test ids uniformization, as well as #146 and https://github.com/pytest-dev/pytest/issues/8155, made me realize that maybe the fixture union engine could be extended to natively support hybrid param+fixture unions.
If this works this would have two benefits:
- first,
@parametrizewould not have to generate a global union fixture for the parameters as of today, immediately solving #146 - second,
@parametrizewould not have to generate one fixture per group of parameters, so in particular@parametrize_with_caseswould probably be much more efficient (far less fixtures generated, only when a case requires a fixture)
However... it will probably be hard to do. A few things to do:
-
UnionFixtureAlternative.to_list_of_fixture_nameswill have to only return only the fixtures and not the parameters https://github.com/smarie/python-pytest-cases/blob/aeb72ef30fd71d8cb332d7d1d55b60159ebc198d/pytest_cases/plugin.py#L295 so thatFixtureClosureNode._build_closurecan understand https://github.com/smarie/python-pytest-cases/blob/aeb72ef30fd71d8cb332d7d1d55b60159ebc198d/pytest_cases/plugin.py#L246 -
modify the calls reactor behaviour when it receives a Union Param https://github.com/smarie/python-pytest-cases/blob/aeb72ef30fd71d8cb332d7d1d55b60159ebc198d/pytest_cases/plugin.py#L760 and when it processes it: https://github.com/smarie/python-pytest-cases/blob/aeb72ef30fd71d8cb332d7d1d55b60159ebc198d/pytest_cases/plugin.py#L834
-
finally checking how the ids in all the tests will evolve and how/if we should adapt idstyle
Not an easy ride but might be worth the shot in 2021
After sleeping on this I think the right order would better be:
-
@parametrizedoes not need to create a test wrapper anymore. It needs to stop creatingParamAlternatives and instead just pass the argvalues as is. All argvalues containingfixture_ref, possibly marked, possibly nested in tuples, etc., need to be replaced with an easier to use object for exampleValueWithFixtureRefs, remembering if the fixture ref is used for the whole tuple or for parts of it (possibly several).
-
- in
FixtureClosureNode._build_closure, we should check that the corresponding parameter still pops in the received list. There is a need to detect that this parameter is special (because it contains fixture_refs). For this, the argvalues are currently inspected with https://github.com/smarie/python-pytest-cases/blob/b0681bb12e479469d416da1ce5688ba5838b3d3e/pytest_cases/fixture_core1_unions.py#L15 . This should therefore be modified so that it returns true if at least oneValueWithFixtureRefsis detected in the list.
- in
-
- In the
pytest_runtest_setuphook, this specialValueWithFixtureRefsobject will probably need to be resolved usingrequest._getfixture(?). For this a convenienceValueWithFixtureRefs.resolve(self, request_or_item)method on the object seems appropriate. https://github.com/smarie/python-pytest-cases/blob/aeb72ef30fd71d8cb332d7d1d55b60159ebc198d/pytest_cases/plugin.py#L60
- In the
Another way to say the above is "before I thought that fixture unions were the core and parametrize would reuse this, but we have to revert this pattern: a fixture union is "just" a parametrized fixture with only fixture_ref argvalues. So @parametrize should be the core mechanism.
Another thing we'll need to do in this refactoring, as discussed in #158, is to support parametrized lazy_value and lazy_value requiring fixtures. This would enable us to remove all the fixture-creating "tricks" in @parametrize_with_cases.
This plan becomes clearer and clearer, I'm optimistic for 2021 ! But as always, devil will be in the tiny details: custom ids, custom marks, custom fixture scopes, etc.