pytest-dev / pytest-dev/pytest

Keyword-based parameter sets

Open
#9,216 14 comments 7 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

topic: parametrize type: proposal
Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

In many of my tests I've been using pytest.param(..., id="...") as means of providing more readable identifiers for my tests inline, since otherwise with multiple parameters, the autogenerated id is hard to read.

Some of my parameter-driven tests end up growing beyond 2-3 arguments and maintaining the parameters positionally becomes error-prone and hurts readability. The reader has to mentally "zip" a list of parameters (of a parameter set) to the parameter names defined earlier, and if you need to add a parameter, now you need to add them to each and every test, and if you want to insert it (e.g. to maintain grouping), you'd have to carefully count parameters in each of the sets.

One pattern I've been introducing in such cases is defining a "ParamSet" attrs base class:

import attr


@attr.s(auto_attribs=True, kw_only=True)
class ParamSet:
    """
    Use as base class for sets for parameters for @pytest.mark.parametrize
    when you find yourself passing too many parameters positionally.
    """

    id: str

    @property
    def __name__(self) -> str:  # indicate the id to pytest
        return self.id

From there, a test would look like:

@attr.s(auto_attribs=True, kw_only=True)
class MyComplexTestParamSet(ParamSet):
   foo: int
   bar: str = 'some_default'
   expected_baz: float


@pytest.mark.parameterize('params', [
   MyComplexTestParamSet(foo=42, expected_baz=42.42, id="happy path"),
   ...
])
def test_complex(params: MyComplexTestParamSet):
   ...

Before we discuss specifics, is this something we'd want pytest.param to enable?

To give an idea, I'd imagine usage like:

@pytest.mark.parameterize('params', [
   pytest.param(foo=42, expected_baz=42.42, id="happy path"),
   ...
])
def test_complex(params: Any):
   ...

or something more typed like this: (I like the fact that the type hint enables better developer experience when working on the test)

class MyComplexTestParamSet(pytest.ParameterSet):
  foo: int
  ...

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the current pytest.param and @pytest.mark.parametrize entry points, focusing on how parameter values and readable IDs are represented. Compare the requested keyword-based and typed ParameterSet examples with existing behavior. Done means establishing whether a coherent API and scope can be defined; the issue does not name implementation files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.