




















@@ -7,7 +7,14 @@
77from datetime import date, timedelta
88from unittest import TestCase, main
9910-from model_usage import filter_by_days, positive_int
10+from model_usage import (
11+aggregate_costs,
12+coerce_finite_cost,
13+filter_by_days,
14+latest_day_cost,
15+pick_current_model,
16+positive_int,
17+)
111812191320class TestModelUsage(TestCase):
@@ -35,6 +42,111 @@ def test_filter_by_days_keeps_recent_entries(self):
3542self.assertEqual(filtered[0]["date"], (today - timedelta(days=1)).strftime("%Y-%m-%d"))
3643self.assertEqual(filtered[1]["date"], today.strftime("%Y-%m-%d"))
374445+def test_coerce_finite_cost_accepts_numbers_and_numeric_strings(self):
46+self.assertEqual(coerce_finite_cost(2), 2.0)
47+self.assertEqual(coerce_finite_cost(1.75), 1.75)
48+self.assertEqual(coerce_finite_cost("1.75"), 1.75)
49+self.assertEqual(coerce_finite_cost(" 2.5 "), 2.5)
50+51+def test_coerce_finite_cost_rejects_booleans(self):
52+# bool is a subclass of int in Python, but is never a valid cost.
53+self.assertIsNone(coerce_finite_cost(True))
54+self.assertIsNone(coerce_finite_cost(False))
55+56+def test_coerce_finite_cost_rejects_non_finite(self):
57+self.assertIsNone(coerce_finite_cost(float("nan")))
58+self.assertIsNone(coerce_finite_cost(float("inf")))
59+self.assertIsNone(coerce_finite_cost(float("-inf")))
60+self.assertIsNone(coerce_finite_cost("NaN"))
61+self.assertIsNone(coerce_finite_cost("Infinity"))
62+63+def test_coerce_finite_cost_rejects_unusable_values(self):
64+self.assertIsNone(coerce_finite_cost("not-a-number"))
65+self.assertIsNone(coerce_finite_cost(""))
66+self.assertIsNone(coerce_finite_cost(None))
67+self.assertIsNone(coerce_finite_cost({}))
68+69+def test_aggregate_costs_includes_numeric_strings(self):
70+entries = [
71+ {
72+"date": "2026-05-25",
73+"modelBreakdowns": [
74+ {"modelName": "claude-sonnet-4-6", "cost": 1.50},
75+ {"modelName": "claude-sonnet-4-6", "cost": "1.75"},
76+ ],
77+ }
78+ ]
79+self.assertEqual(aggregate_costs(entries), {"claude-sonnet-4-6": 3.25})
80+81+def test_aggregate_costs_ignores_bool_and_non_finite(self):
82+entries = [
83+ {
84+"date": "2026-05-25",
85+"modelBreakdowns": [
86+ {"modelName": "claude-sonnet-4-6", "cost": 1.50},
87+ {"modelName": "claude-sonnet-4-6", "cost": "1.75"},
88+ {"modelName": "claude-sonnet-4-6", "cost": True},
89+ {"modelName": "claude-sonnet-4-6", "cost": float("nan")},
90+ {"modelName": "claude-sonnet-4-6", "cost": float("inf")},
91+ ],
92+ }
93+ ]
94+totals = aggregate_costs(entries)
95+# NaN/Infinity must not poison the total; bool must not add 1.0.
96+self.assertEqual(totals, {"claude-sonnet-4-6": 3.25})
97+98+def test_pick_current_model_scores_numeric_string_costs(self):
99+# model-b's cost is a numeric string; it must still win on highest cost.
100+entries = [
101+ {
102+"date": "2026-05-25",
103+"modelBreakdowns": [
104+ {"modelName": "model-a", "cost": 1.0},
105+ {"modelName": "model-b", "cost": "5.0"},
106+ ],
107+ }
108+ ]
109+model, day = pick_current_model(entries)
110+self.assertEqual(model, "model-b")
111+self.assertEqual(day, "2026-05-25")
112+113+def test_pick_current_model_ignores_bool_and_non_finite(self):
114+# Only model-a has a usable cost; bool and NaN must not be scored.
115+entries = [
116+ {
117+"date": "2026-05-25",
118+"modelBreakdowns": [
119+ {"modelName": "model-a", "cost": 2.0},
120+ {"modelName": "model-b", "cost": True},
121+ {"modelName": "model-c", "cost": float("nan")},
122+ ],
123+ }
124+ ]
125+model, _day = pick_current_model(entries)
126+self.assertEqual(model, "model-a")
127+128+def test_latest_day_cost_accepts_numeric_string(self):
129+entries = [
130+ {
131+"date": "2026-05-25",
132+"modelBreakdowns": [{"modelName": "model-a", "cost": "2.50"}],
133+ }
134+ ]
135+day, cost = latest_day_cost(entries, "model-a")
136+self.assertEqual(day, "2026-05-25")
137+self.assertEqual(cost, 2.50)
138+139+def test_latest_day_cost_rejects_non_finite(self):
140+entries = [
141+ {
142+"date": "2026-05-25",
143+"modelBreakdowns": [{"modelName": "model-a", "cost": float("inf")}],
144+ }
145+ ]
146+day, cost = latest_day_cost(entries, "model-a")
147+self.assertEqual(day, "2026-05-25")
148+self.assertIsNone(cost)
149+3815039151if __name__ == "__main__":
40152main()
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。