Refactor the types tests
Marco Ricci

Marco Ricci commited on 2025-08-17 16:01:53
Zeige 2 geänderte Dateien mit 66 Einfügungen und 66 Löschungen.


(This is part 2 of a series of refactorings for the test suite.)

For the basic tests, collect all test data in a common class
`Strategies` (similar to the `Parametrize` class).  Split them into
groups for validity testing and validation/data cleaning.  For each
group, factor out the common test operation... which in both cases, is
the whole test content, save for the different input data set they run
on.

For the heavy-duty tests, there is only one data generation strategy,
which needn't artifically be wrapped in a class (yet).  There is also
only one test, so there is no need for further grouping either.
Instead, add some missing commentary on the one explicit example in that
test set.
... ...
@@ -16,14 +16,19 @@ from tests import data
16 16
 from tests.machinery import hypothesis as hypothesis_machinery
17 17
 
18 18
 
19
+class Strategies:
20
+    VALID_VAULT_TEST_CONFIGS = tuple(
21
+        conf for conf in data.TEST_CONFIGS if conf.is_valid()
22
+    )
23
+    SMUDGABLE_VAULT_TEST_CONFIGS = tuple(
24
+        conf for conf in data.TEST_CONFIGS if conf.is_smudgable()
25
+    )
26
+
27
+
19 28
 class Parametrize(types.SimpleNamespace):
20 29
     VALID_VAULT_TEST_CONFIGS = pytest.mark.parametrize(
21 30
         "test_config",
22
-        [
23
-            conf
24
-            for conf in data.TEST_CONFIGS
25
-            if conf.validation_settings in {None, (True,)}
26
-        ],
31
+        Strategies.VALID_VAULT_TEST_CONFIGS,
27 32
         ids=data.VaultTestConfig._test_id,
28 33
     )
29 34
     VAULT_TEST_CONFIGS = pytest.mark.parametrize(
... ...
@@ -33,8 +38,25 @@ class Parametrize(types.SimpleNamespace):
33 38
     )
34 39
 
35 40
 
41
+class TestVaultConfig:
42
+    """Test `vault` configuration detection."""
43
+
44
+    @staticmethod
45
+    def _test(test_config: data.VaultTestConfig) -> None:
46
+        config, comment, _ = test_config
47
+        obj = copy.deepcopy(config)
48
+        did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
49
+        assert _types.is_vault_config(obj) == (not comment), (
50
+            "failed to complain about: " + comment
51
+            if comment
52
+            else "failed on valid example"
53
+        )
54
+        assert did_cleanup is None or bool(did_cleanup) == (obj != config), (
55
+            "mismatched report on cleanup work"
56
+        )
57
+
36 58
     @Parametrize.VALID_VAULT_TEST_CONFIGS
37
-def test_is_vault_config(test_config: data.VaultTestConfig) -> None:
59
+    def test_is_config(self, test_config: data.VaultTestConfig) -> None:
38 60
         """Is this vault configuration recognized as valid/invalid?
39 61
 
40 62
         Check all test configurations that do not need custom validation
... ...
@@ -44,15 +66,7 @@ def test_is_vault_config(test_config: data.VaultTestConfig) -> None:
44 66
         [`_types.clean_up_falsy_vault_config_values`][] functions.
45 67
 
46 68
         """
47
-    obj, comment, _ = test_config
48
-    obj = copy.deepcopy(obj)
49
-    _types.clean_up_falsy_vault_config_values(obj)
50
-    assert _types.is_vault_config(obj) == (not comment), (
51
-        "failed to complain about: " + comment
52
-        if comment
53
-        else "failed on valid example"
54
-    )
55
-
69
+        self._test(test_config)
56 70
 
57 71
     @hypothesis.given(
58 72
         test_config=hypothesis_machinery.smudged_vault_test_config(
... ...
@@ -61,7 +75,8 @@ def test_is_vault_config(test_config: data.VaultTestConfig) -> None:
61 75
             ])
62 76
         )
63 77
     )
64
-def test_is_vault_config_smudged(
78
+    def test_is_config_even_if_smudged(
79
+        self,
65 80
         test_config: data.VaultTestConfig,
66 81
     ) -> None:
67 82
         """Is this vault configuration recognized as valid/invalid?
... ...
@@ -73,36 +88,20 @@ def test_is_vault_config_smudged(
73 88
         [`_types.clean_up_falsy_vault_config_values`][] functions.
74 89
 
75 90
         """
76
-    obj_, comment, _ = test_config
77
-    obj = copy.deepcopy(obj_)
78
-    did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
79
-    assert _types.is_vault_config(obj) == (not comment), (
80
-        "failed to complain about: " + comment
81
-        if comment
82
-        else "failed on valid example"
83
-    )
84
-    assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), (
85
-        "mismatched report on cleanup work"
86
-    )
91
+        self._test(test_config)
87 92
 
88 93
 
89
-@Parametrize.VAULT_TEST_CONFIGS
90
-def test_validate_vault_config(
94
+class TestVaultConfigValidation:
95
+    """Test the validation of `vault` configurations."""
96
+
97
+    def _test(
98
+        self,
91 99
         test_config: data.VaultTestConfig,
92 100
     ) -> None:
93
-    """Validate this vault configuration.
94
-
95
-    Check all test configurations, including those with non-standard
96
-    validation settings.
97
-
98
-    This primarily tests the [`_types.validate_vault_config`][] and
99
-    [`_types.clean_up_falsy_vault_config_values`][] functions.
100
-
101
-    """
102
-    obj, comment, validation_settings = test_config
101
+        config, comment, validation_settings = test_config
103 102
         (allow_unknown_settings,) = validation_settings or (True,)
104
-    obj = copy.deepcopy(obj)
105
-    _types.clean_up_falsy_vault_config_values(obj)
103
+        obj = copy.deepcopy(config)
104
+        did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
106 105
         if comment:
107 106
             with pytest.raises((TypeError, ValueError)):
108 107
                 _types.validate_vault_config(
... ...
@@ -115,9 +114,27 @@ def test_validate_vault_config(
115 114
                     obj,
116 115
                     allow_unknown_settings=allow_unknown_settings,
117 116
                 )
118
-        except (TypeError, ValueError) as exc:  # pragma: no cover
119
-            assert not exc, "failed to validate valid example"  # noqa: PT017
117
+            except (TypeError, ValueError):  # pragma: no cover
118
+                pytest.fail("failed to validate valid example")
119
+        assert did_cleanup is None or bool(did_cleanup) == (obj != config), (
120
+            "mismatched report on cleanup work"
121
+        )
122
+
123
+    @Parametrize.VAULT_TEST_CONFIGS
124
+    def test_validate_config(
125
+        self,
126
+        test_config: data.VaultTestConfig,
127
+    ) -> None:
128
+        """Validate this vault configuration.
129
+
130
+        Check all test configurations, including those with non-standard
131
+        validation settings.
132
+
133
+        This primarily tests the [`_types.validate_vault_config`][] and
134
+        [`_types.clean_up_falsy_vault_config_values`][] functions.
120 135
 
136
+        """
137
+        self._test(test_config)
121 138
 
122 139
     @hypothesis.given(
123 140
         test_config=hypothesis_machinery.smudged_vault_test_config(
... ...
@@ -126,7 +143,8 @@ def test_validate_vault_config(
126 143
             ])
127 144
         )
128 145
     )
129
-def test_validate_vault_config_smudged(
146
+    def test_validate_config_even_if_smudged(
147
+        self,
130 148
         test_config: data.VaultTestConfig,
131 149
     ) -> None:
132 150
         """Validate this vault configuration.
... ...
@@ -138,24 +156,4 @@ def test_validate_vault_config_smudged(
138 156
         [`_types.clean_up_falsy_vault_config_values`][] functions.
139 157
 
140 158
         """
141
-    obj_, comment, validation_settings = test_config
142
-    (allow_unknown_settings,) = validation_settings or (True,)
143
-    obj = copy.deepcopy(obj_)
144
-    did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
145
-    if comment:
146
-        with pytest.raises((TypeError, ValueError)):
147
-            _types.validate_vault_config(
148
-                obj,
149
-                allow_unknown_settings=allow_unknown_settings,
150
-            )
151
-    else:
152
-        try:
153
-            _types.validate_vault_config(
154
-                obj,
155
-                allow_unknown_settings=allow_unknown_settings,
156
-            )
157
-        except (TypeError, ValueError) as exc:  # pragma: no cover
158
-            assert not exc, "failed to validate valid example"  # noqa: PT017
159
-    assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), (
160
-        "mismatched report on cleanup work"
161
-    )
159
+        self._test(test_config)
... ...
@@ -68,7 +68,9 @@ def js_nested_strategy(draw: strategies.DrawFn) -> Any:
68 68
 
69 69
 
70 70
 @hypothesis.given(value=js_nested_strategy())
71
-@hypothesis.example(float("nan"))
71
+@hypothesis.example(float("nan")).via(
72
+    "for branch coverage in the implementation"
73
+)
72 74
 def test_js_truthiness(value: Any) -> None:
73 75
     """Determine the truthiness of a value according to JavaScript.
74 76
 
75 77