pytest-dev / pytest-dev/pytest

Test case naming function (alternative to ids=)

Open
#6,837 4 comments 1 reaction 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

After migration to pytest, I am frequently missing feature with regard to test parametrization that I used in the parameterized library:

Ability to generate test ID based on the entire set of values.

In parameterized, this has been implemented as an testcase_func_name argument, which is similar to the ids argument. With one notable exception:

  • ids operates on individual values
  • testcase_func_name operates on the entire set of values

The latter is much more flexible when it comes to dropping, reordering or combining values.

At the moment, I'm forced to use utility functions instead that take take a list of example values and map it to pytest.param:

def named_test_cases(func: Callable[..., str], params: List[Tuple]) -> List[ParameterSet]:
    return [pytest.param(*param, id=func(*param)) for param in params]

and use it as:

class TestInOperator:
    @staticmethod
    @pytest.mark.parametrize(
        'collection,value',
        named_test_cases(
            lambda collection, value: f"{value} in {collection.__class__.__name__}",
            [([1], 1), ({1: 1}, 1)]
        )
    )
    def test_should_work_on(collection, value):
        assert value in collection

(artificial example for shortness, I'm sure you can imagine more creative ways of combining the values)

Or even simpler, allowing a string that is treated as an input for str.format():

def named_test_cases(format_string: str, params: List[Tuple]) -> List[ParameterSet]:
    return [pytest.param(*param, id=format_string.format(*param)) for param in params]

and use it as:

...
named_test_cases(
    "{1} in {0.__class__.__name__}",
    [([1], 1), ({1: 1}, 1)]
)
...

You can see this is a short and elegant way of providing well readable names for test cases.

I searched the existing issues and the closest one on similar topic was #6335. I agree with not modifying the existing ids argument that is already quite complex. However, would it be an option to implement functionality similar to above using new argument(s)? (testcase_func_name, testcase_format_name, or anything else)

The end results could look something like:

class TestInOperator:
    @staticmethod
    @pytest.mark.parametrize(
        'collection,value',
        [([1], 1), ({1: 1}, 1)],
        testcase_format_name="{1} in {0.__class__.__name__}",
    )
    def test_should_work_on(collection, value):
        assert value in collection

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

Start by reviewing pytest.mark.parametrize and its existing ids argument, then read the discussion in issue #6335 for related design context. Define and test a naming option that receives the full parameter set, supporting the callable or format-string behavior described here; done means generated test IDs reflect combined, reordered, or omitted values.

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
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.