Description
What's the problem this feature will solve?
Since pytest >= 8.4.0
the check that fixtures are of type FixtureFunctionDefinition
causes issues for plugins. One such plugin that I use in my test suite is pytest_lambda
.
Now, I'm not sure this is the case for all, but one could easily argue that these plugins rely on internal implementation details that are not guaranteed and subject to change, so caveat emptor. Nevertheless, they worked and are now broken.
pytest_lambda
specifically relied on returning an instance of itself from its lambda_fixture
function. Later it would resolve fixtures into the actual underlying calls. To do this it relied on PytestWrapped
and other internals which no longer exist.
I'm a mere user of it, but I've attempted to make some changes to make it work with pytest >= 8.4.0
.
In doing so, one restriction that has been problematic is the check in parsefactories
:
if type(obj_ub) is FixtureFunctionDefinition:
marker = obj_ub._fixture_function_marker
This forces the return from all fixture generating functions to be the exact type FixtureFunctionDefinition
. You can't subclass it or the type won't match.
pytest_lambda
against older pytest supports various nice syntaxes to declare fixtures (see https://pypi.org/project/pytest-lambda/). In order to support these, without being able to subclass FixtureFunctionDefinition
requires hackery to replace the __class__
/type
with a different type, detect this later in the plugin when its iterating over all names in pytest_collectstart
or pytest_pycollect_makeitem
, do what's necessary with the derived type and then replace the __class__
attribute so the fixture gets registered.
It feels like this would be a lot less brittle if there was an officially supported way to do such things. An easy way would appear to be allowing subclasses of FixtureFunctionDefinition
.
NOTE - I did try to invert the logic in pytest_lambda
to remove all dependence on internal and just call pytest.fixture
from pytest_lambda
code, but that suffers the same issue in that it doesn't expose hooks to allow for more advanced usage (e.g. destructuring the return value of a fixture generation function by returning an iterator instead of a FixtureFunctionDefinition
).
Describe the solution you'd like
Make FixtureFunctionDefinition
an exposed type (i.e. in pytest
namespace) and allow subclassing of to enable more advanced fixture generation.
Alternatively, provide an alternative means to do the same.
Additional context
Problematic scenarios/syntaxes:
# Destructuring the return value. Requires hacking an iterator onto FixtureFunctionDefinition
x, y, z = lambda_fixture('aa', 'bb', 'cc')
# Destructuring param values (used to generate parameterised tests)
# I don't personally use this, but was attempting to keep feature parity
pa, pb, pc, pd = lambda_fixture(params=[
pytest.param('alfalfa', 'better', 'dolt', 'gamer'),
])