tenseleyflow/sway / 3653ba3

Browse files

tests/cli: doctor --json schema-shape snapshot (stronger-test #11)

Authored by espadonne
SHA
3653ba3eb36c59f39b1480b895309003e1a6c4c2
Parents
277fbdc
Tree
01ff996

1 changed file

StatusFile+-
M tests/unit/test_cli.py 32 0
tests/unit/test_cli.pymodified
@@ -123,6 +123,38 @@ class TestDoctorJson:
123123
         assert "httpx" in payload["extras"]["api"]
124124
         assert "tenacity" in payload["extras"]["api"]
125125
 
126
+    def test_json_schema_is_snapshot_stable(self) -> None:
127
+        """Stronger-test #11 — pin ``sway doctor --json``'s *shape*
128
+        (top-level keys + extras bucket keys + their contents as sets of
129
+        module names). Values (``sway_version``, ``python``, ``platform``,
130
+        installed vs missing) vary by host and are masked so the snapshot
131
+        catches structural drift without being environment-sensitive."""
132
+        result = CliRunner().invoke(app, ["doctor", "--json"])
133
+        assert result.exit_code == 0
134
+        payload = json.loads(result.stdout)
135
+
136
+        assert set(payload) == {"sway_version", "python", "platform", "extras"}
137
+        # Every extra bucket's keys are stable; values (module versions)
138
+        # are not. Snapshot the sorted module-name set per bucket.
139
+        extras = payload["extras"]
140
+        assert isinstance(extras, dict)
141
+        extras_shape = {bucket: sorted(extras[bucket]) for bucket in sorted(extras)}
142
+        assert extras_shape == {
143
+            "api": ["httpx", "tenacity"],
144
+            "dlm": ["dlm"],
145
+            "hf": ["peft", "torch", "transformers"],
146
+            "mlx": ["mlx", "mlx_lm"],
147
+            "pytest": ["pytest"],
148
+            "semsim": ["sentence_transformers", "sklearn"],
149
+            "style": ["nlpaug", "spacy", "textstat"],
150
+            "viz": ["matplotlib", "plotly"],
151
+        }
152
+        # Value type is str-or-None on every module entry.
153
+        for bucket_name, bucket in extras.items():
154
+            for mod_name, version in bucket.items():
155
+                assert isinstance(mod_name, str), bucket_name
156
+                assert version is None or isinstance(version, str), (bucket_name, mod_name)
157
+
126158
 
127159
 class TestListProbes:
128160
     """D6: ``sway list-probes`` prints the registered kinds."""