8000 How to mark up fixtures with metadata for segregating collections of fixtures in scope · Issue #11462 · pytest-dev/pytest · GitHub
[go: up one dir, main page]

Skip to content

How to mark up fixtures with metadata for segregating collections of fixtures in scope #11462

@jxramos

Description

@jxramos

What's the problem this feature will solve?

The problem to be solved here is how to organize families of fixtures with pure metadata to avoid looking up fixture values from their names to determine if the fixture belongs to a given family or not.

I'm looking for a way that I can mark up a bunch of fixtures spread around a bunch of plugin and conftest files etc some of which are marked up with the simple standard markers pytest.mark.metaFoo. I wish to then lookup those marks from the FixtureDef instances retained in the fixture manager to do some dynamic container creations from these fixture families identified by their markers alone. I wish to do this family identification via markers because fixture naming convention alone is inadequate for my use case where looking up fixture values for those fixtures which match a naming convention can cause recursion loops for those fixtures that hold dependencies on the fixture I'm trying to dynamically populate with the fixtures of a given family but not others. This is where marker metadata would be a powerful differentiator.

Describe the solution you'd like

I'd like to be able to decorate my fixtures with regular pytest markers as such (which is valid syntax today) but with that marker metadata able to be crawled and looked up from the request fixture object and ideally populated in the FixtureDef instances.

# plugin_1.py
import pytest
@pytest.mark.fixA
@pytest.mark.other
@pytest.fixture
def fixture_foo():
    return "foo"

@pytest.mark.fixB
@pytest.fixture
def fixture_bar():
    return "bar"


# plugin_2.py
import pytest

@pytest.mark.fixA
@pytest.fixture
def fixture_2foo():
    return "2foo"

@pytest.mark.fixB
@pytest.fixture
def fixture_2bar():
    return "2bar"

From the above I need a fixture that dynamically returns a container of the fixture values ["foo", "2foo"] just by discovering the fixtures in scope and contributing to that container the values of all fixtures which match the family criteria corresponding to the pytest markers I wish to filter upon.

Alternative Solutions

So far I've been leaning on a combination of fixture naming conventions and value lookups to get this organization by families accomplished but that will not work when I get to the complex case where the different fixture subfamilies share the same naming convention and thus become undifferentiable. In that scenario the fixtures are given different definitions from alternate plugins where I don't want them to continue to be selected by name anymore because the naming convention then blurs between two families of fixtures that have no way to be differentiated by name alone (hence the need for the markers to do the job).

Here's the partial solution I've attempted so far that lets me organize fixtures by the naming convention pattern matching a suffix

@pytest.fixture(autouse=True)
def fix_list(request):
    print("fix_list")
    foo_fixtures = [request.getfixturevalue(fix_name) for fix_name in request._fixturemanager._arg2fixturedefs if fix_name.endswith("_foo")]
    return foo_fixtures

https://stackoverflow.com/a/77154959/1330381

Additional context

When I probe the fixture definition from a global scope I see that the fixtures have a pytestmark attribute, eg

fixture_foo.pytestmark
[Mark(name='fixA', args=(), kwargs={}), Mark(name='other', args=(), kwargs={})]

I can't see how to navigate to that data from the request fixture. If there is an existing means today that would solve all my problems and I could mark up my fixtures today and solve some gnarly problems.

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: fixturesanything involving fixtures directly or indirectlytopic: marksrelated to marks, either the general marks or builtintype: questiongeneral question, might be closed after 2 weeks of inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0