pytest icon indicating copy to clipboard operation
pytest copied to clipboard

Add typing information for parameterized fixtures

Open tobiasdiez opened this issue 4 years ago • 6 comments

What's the problem this feature will solve?

Add typing information for parameterized fixtures to have better support for type checkers.

Describe the solution you'd like

Given a fixture like


@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"])
def mode(request):
    return request.param

what is the type of request? I thought it would be FixtureRequest but this class doesn't have a param object. Thus I suggest to add a generic class ParametrizedFixtureRequest[T] where T is the type of the parameter. Thus in the above example one could annotate request: ParametrizedFixtureRequest[str] and then the type checker would know that request.param is a string.

Alternative Solutions

Additional context

tobiasdiez avatar Nov 25 '20 11:11 tobiasdiez

@bluetech would it be sensible to introduce a generic protocol here ?

RonnyPfannschmidt avatar Nov 25 '20 12:11 RonnyPfannschmidt

Thanks for bringing this up @tobiasdiez.

This seems doable but would require some work:

The param is only found on SubRequest and not on FixtureRequest, and I'm not yet sufficiently familiar with it and its weird relationship with FixtureRequest to say whether and how it should be exposed.

For unparametrized fixtures, pytest currently leaves request.param entirely undefined, i.e. accessing it leads to AttributeError. That's no good for static typing: Python/mypy does not provide a way to model this, there is no undefined type like in JavaScript (luckily).

Python/mypy currently does not support giving defaults to type parameters, so this will be a bit of an ergonomic hit for annotating with FixtureRequest in the non-parametrized case when using the disallow_any_generics mypy option. It will have to be FixtureRequest[None] (or something else depending on the solution to the previous point).

bluetech avatar Nov 25 '20 20:11 bluetech

im happy to have 2 types for that, the fixture decorator could even apply it based on params and/or a flag for the param type required

then mypy would fail with missing attribute for non-parameterized fixtures while giving off the exxact type in the other case

RonnyPfannschmidt avatar Nov 25 '20 22:11 RonnyPfannschmidt

On a related note: I'm happy to just add a param = None to FixtureRequest rather than leave it undefined (or a UNDEFINED sentinel if we want to distinguish between no parametrization vs parametrization with a None value, but I'm not sure of a use case where the distinction makes a difference). The current AttributeError a user gets is very unfriendly.

We did something similar with cached_result.

nicoddemus avatar Nov 27 '20 13:11 nicoddemus

Parameter values may be none, we either have to have a extra flag for indication, or a singleton type

RonnyPfannschmidt avatar Nov 27 '20 14:11 RonnyPfannschmidt

Any plans to implement this feature anytime soon?

leonarduschen avatar Jul 10 '22 07:07 leonarduschen