Repository: pytest-dev/pytest
File: testing/test_collection.py (Python)

Code before:
        ("[(1, 1), (1, 2), (1, 1)]", {"1-1": [0, 2]}),
        ("[(1, 1), (2, 2), (1, 1)]", {"1-1": [0, 2]}),
        ("[(1, 1), (2, 2), (1, 2), (2, 1), (1, 1)]", {"1-1": [0, 4]}),
    ]

    @staticmethod
    def _fnmatch_escape_repr(obj) -> str:
        return re.sub(r"[*?[\]]", (lambda m: f"[{m.group()}]"), repr(obj))

    def _assert_duplicate_msg(self, result, expected_indices):
        stream = result.stdout
        stream.fnmatch_lines(
            [
                "When --require-unique-parameterization-ids set, pytest won't generate unique IDs for parameters.",
                "test name: *::test1",
                "argument names: [[]'y', 'x'[]]",
                f"duplicates: {self._fnmatch_escape_repr(expected_indices)}",
                "you must make sure all parameterization IDs are unique, either by:",
                "- providing unique IDs per parameterization via the ids=[...] argument to @pytest.mark.parametrize",
                "- providing a custom id function that generates unique IDs for each parameterization",
                "- not setting --require-unique-parameterization-ids",
            ]
        )
        assert result.ret != 0

    @pytest.mark.parametrize("parametrize_args, expected_indices", CASES)
    def test_cli_enables(self, pytester: Pytester, parametrize_args, expected_indices):
        pytester.makepyfile(
            f"""
            import pytest

            @pytest.mark.parametrize('y, x', {parametrize_args})
            def test1(y, x):
                pass
            """
        )
        result = pytester.runpytest("--require-unique-parameterization-ids")
        self._assert_duplicate_msg(result, expected_indices)

    @pytest.mark.parametrize("parametrize_args, expected_indices", CASES)
    def test_ini_enables(self, pytester: Pytester, parametrize_args, expected_indices):
        pytester.makeini(
            """
            [pytest]
            require_unique_parameterization_ids = true
            """
        )
        pytester.makepyfile(
            f"""
                    import pytest


Review comment (suggestion):
The `"x,y"` syntax is ~sort of legacy, better to write them out as separate strings:

```suggestion
    @pytest.mark.parametrize(("parametrize_args", "expected_indices"), CASES)
```

Code after:
        (
            [(1, 1), (1, 1)],
            ["1-1"],
        ),
        (
            [(1, 1), (1, 2), (1, 1)],
            ["1-1"],
        ),
        (
            [(1, 1), (2, 2), (1, 1)],
            ["1-1"],
        ),
        (
            [(1, 1), (2, 2), (1, 2), (2, 1), (1, 1), (2, 1)],
            ["1-1", "2-1"],
        ),
    ],
)
def test_strict_parametrization_ids(
    pytester: Pytester,
    x_y: Sequence[tuple[int, int]],
    expected_duplicates: Sequence[str],
) -> None:
    pytester.makeini(
        """
        [pytest]
        strict_parametrization_ids = true
        """
    )
    pytester.makepyfile(
        f"""
        import pytest

        @pytest.mark.parametrize(["x", "y"], {x_y})
        def test1(x, y):
            pass
        """
    )

    result = pytester.runpytest()

    assert result.ret == ExitCode.INTERRUPTED
    expected_parametersets = ", ".join(str(list(p)) for p in x_y)
    expected_ids = ", ".join(f"{x}-{y}" for x, y in x_y)
    result.stdout.fnmatch_lines(
        [
            "Duplicate parametrization IDs detected*",
            "",
            "Test name:      *::test1",
            "Parameters:     x, y",
            f"Parameter sets: {expected_parametersets}",