Skip to content

API to get a test's fixture definitions during parametrization #14991

Description

@tjkuson

What's the problem this feature will solve?

During pytest_generate_tests, I want to be able to get the functions that define a test's fixture dependencies to determine whether and how to parametrize the test (including fixtures requested via other fixtures).

Specifically, pytest-asyncio can run tests with different event loop configurations. It needs to apply this parametrization to all tests that use its async fixtures, including sync tests.

Describe the solution you'd like

A public API on Metafunc to get the fixture definitions upon which a test depends, without running the fixtures.

pytest.FixtureDef is already public. What I am looking for is a way to get the definitions used by a particular test during pytest_generate_tests.

Something like this could work:

def pytest_generate_tests(metafunc):
    funcs = [fd.func for fd in metafunc.fixturedefs]  # proposed new metafunc.fixturedefs API
    # use the above to decide whether to call metafunc.parametrize(...), etc.

Metafunc.fixturedefs could be a read-only property that returns a tuple of pytest.FixtureDef objects. My specific use case needs supported access to each definition's .func, though. The returned fixture definitions for a test should follow fixture resolution rules (i.e., handle the different ways to request a fixture, overrides, and fixture configuration via parametrization).

I don't need a fixed iteration order or for the API to pre-empt future changes to the dependencies (I'm not sure it'd even be possible to deal with future parametrization). It would be fine (and, IMO, intuitive) for each access to reflect the fixture definitions so far. I'd like the plugin to be able to read the dependencies after other hooks apply parametrization, and then apply further parametrization itself.

Alternative Solutions

There doesn't seem to be a solution at the moment other than attempting to re-implement fixture resolution via private APIs.

This mapping gives access to fixture definitions:

fixturedefs = metafunc._arg2fixturedefs["resource"]
functions = [fixturedef.func for fixturedef in fixturedefs]

However, it includes definitions that the test does not use.

# conftest.py
import pytest

@pytest.fixture
def resource():
    return "base"
# test_example.py
import pytest

@pytest.fixture
def resource(resource):
    return resource

def test_example(resource):
    pass

Here, the mapping contains both resource definitions, and the proposed API should return both functions. If the local fixture takes no arguments and returns "replacement", the mapping still contains both definitions. The proposed API should then return only the local fixture function.

The private traverse_fixture_closure function resolves dependency names, but does not return the definitions it visits.

Additional context

This would help close pytest-dev/pytest-asyncio#1501.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions