|
5 | 5 | from pathlib import Path |
6 | 6 | from pathlib import PurePath |
7 | 7 | import pprint |
| 8 | +import re |
8 | 9 | import shutil |
9 | 10 | import sys |
10 | 11 | import tempfile |
@@ -2702,3 +2703,86 @@ def test_1(): pass |
2702 | 2703 | ], |
2703 | 2704 | consecutive=True, |
2704 | 2705 | ) |
| 2706 | + |
| 2707 | + |
| 2708 | +class TestRequireUniqueParamsetIds: |
| 2709 | + CASES = [ |
| 2710 | + ("[(1, 1), (1, 1)]", {"1-1": [0, 1]}), |
| 2711 | + ("[(1, 1), (1, 2), (1, 1)]", {"1-1": [0, 2]}), |
| 2712 | + ("[(1, 1), (2, 2), (1, 1)]", {"1-1": [0, 2]}), |
| 2713 | + ("[(1, 1), (2, 2), (1, 2), (2, 1), (1, 1)]", {"1-1": [0, 4]}), |
| 2714 | + ] |
| 2715 | + |
| 2716 | + @staticmethod |
| 2717 | + def _fnmatch_escape_repr(obj) -> str: |
| 2718 | + return re.sub(r"[*?[\]]", (lambda m: f"[{m.group()}]"), repr(obj)) |
| 2719 | + |
| 2720 | + def _assert_duplicate_msg(self, result, expected_indices): |
| 2721 | + stream = result.stdout |
| 2722 | + stream.fnmatch_lines( |
| 2723 | + [ |
| 2724 | + "When --require-unique-parameterization-ids set, pytest won't generate unique IDs for parameters.", |
| 2725 | + "test name: *::test1", |
| 2726 | + "argument names: [[]'y', 'x'[]]", |
| 2727 | + f"duplicates: {self._fnmatch_escape_repr(expected_indices)}", |
| 2728 | + "you must make sure all parameterization IDs are unique, either by:", |
| 2729 | + "- providing unique IDs per parameterization via the ids=[...] argument to @pytest.mark.parametrize", |
| 2730 | + "- providing a custom id function that generates unique IDs for each parameterization", |
| 2731 | + "- not setting --require-unique-parameterization-ids", |
| 2732 | + ] |
| 2733 | + ) |
| 2734 | + assert result.ret != 0 |
| 2735 | + |
| 2736 | + @pytest.mark.parametrize("parametrize_args, expected_indices", CASES) |
| 2737 | + def test_cli_enables(self, pytester: Pytester, parametrize_args, expected_indices): |
| 2738 | + pytester.makepyfile( |
| 2739 | + f""" |
| 2740 | + import pytest |
| 2741 | +
|
| 2742 | + @pytest.mark.parametrize('y, x', {parametrize_args}) |
| 2743 | + def test1(y, x): |
| 2744 | + pass |
| 2745 | + """ |
| 2746 | + ) |
| 2747 | + result = pytester.runpytest("--require-unique-parameterization-ids") |
| 2748 | + self._assert_duplicate_msg(result, expected_indices) |
| 2749 | + |
| 2750 | + @pytest.mark.parametrize("parametrize_args, expected_indices", CASES) |
| 2751 | + def test_ini_enables(self, pytester: Pytester, parametrize_args, expected_indices): |
| 2752 | + pytester.makeini( |
| 2753 | + """ |
| 2754 | + [pytest] |
| 2755 | + require_unique_parameterization_ids = true |
| 2756 | + """ |
| 2757 | + ) |
| 2758 | + pytester.makepyfile( |
| 2759 | + f""" |
| 2760 | + import pytest |
| 2761 | +
|
| 2762 | + @pytest.mark.parametrize('y, x', {parametrize_args}) |
| 2763 | + def test1(y, x): |
| 2764 | + pass |
| 2765 | + """ |
| 2766 | + ) |
| 2767 | + result = pytester.runpytest() |
| 2768 | + self._assert_duplicate_msg(result, expected_indices) |
| 2769 | + |
| 2770 | + def test_cli_overrides_ini_false(self, pytester: Pytester): |
| 2771 | + """CLI True should override ini False.""" |
| 2772 | + pytester.makeini( |
| 2773 | + """ |
| 2774 | + [pytest] |
| 2775 | + require_unique_parameterization_ids = false |
| 2776 | + """ |
| 2777 | + ) |
| 2778 | + pytester.makepyfile( |
| 2779 | + """ |
| 2780 | + import pytest |
| 2781 | +
|
| 2782 | + @pytest.mark.parametrize('y, x', [(1,1), (1,1)]) |
| 2783 | + def test1(y, x): |
| 2784 | + pass |
| 2785 | + """ |
| 2786 | + ) |
| 2787 | + result = pytester.runpytest("--require-unique-parameterization-ids") |
| 2788 | + self._assert_duplicate_msg(result, {"1-1": [0, 1]}) |
0 commit comments