Skip to content

pytest_generate_tests based on params and marks from previous parametrize #13233

Open
@Anton3

Description

@Anton3

Issue

In userver, we add indirect params to all tests based on marks using pytest_generate_tests.
(See the full story in #13217.)

The issue arises when we want to apply our implicit param only to some of the test items spawned from an already parametrized test:

@pytest.mark.parametrize(
    "foo, bar",
    [
        ("a", "x"),
        pytest.param("b", "y", marks=pytest.mark.my_mark("hmm")),
        pytest.param("c", "z", marks=pytest.mark.my_mark("what")),
    ])
def my_test(foo, bar, my_fixture, ...):
    # ...


def pytest_parametrize_tests(metafunc):
    # metafunc represents a test function before the split into items.
    # How do we set indirect param "my_fixture" based on marks
    # from one of the cases?

The issue has been previously explored: #4050

Proposed syntax

What I want to discuss here is an implementation of that idea, starting with a possible syntax.

# pytest
@dataclasses.dataclass(frozen=True)
class ProtoItem(pytest.Node):
    # essentially CallSpec2 with a rich API from Node
    params: dict[str, object]
    own_markers: list[Mark]

# usage
def pytest_parametrize_tests(metafunc):
    def param_generator(proto_item: pytest.ProtoItem) -> ParameterSet | Sequence[object] | object:
        if (mark := proto_item.get_closest_marker("my_mark")) is not None:
            return (compute_param_value_from_mark(mark),)
        else:
            return (get_some_fallback_value(),)

    metafunc.parametrize(("my_fixture",), param_generator)

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: marksrelated to marks, either the general marks or builtintopic: parametrizerelated to @pytest.mark.parametrizetype: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions