Files
climperor/shared/tests/test_stratz_matchups.py
T
vosonandCursor d6212169af v0.5.109: hero role toolbar, skill side-by-side layout, taller detail panel.
Move role filters between grid and detail, fix skill video/text layout and detail height jump, unify item dividers, drop OpenDota matchup cross, sync docs and assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 00:48:07 +08:00

125 lines
4.2 KiB
Python

"""Unit tests for STRATZ matchup ranking + cache helpers.
Run from repo root:
python -m unittest shared.tests.test_stratz_matchups -v
"""
from __future__ import annotations
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from web.fetch_stratz_meta import ( # noqa: E402
annotate_matchup_cell,
build_matchup_file_payload,
load_previous_matchups,
rank_matchup_lists,
write_json_atomic,
)
class RankMatchupListsTests(unittest.TestCase):
def test_counters_sorted_by_advantage_not_raw_wr(self) -> None:
# Wraith King: wr < 0.5 but positive relative advantage — still a counter.
vs = [
{
"hero_id": 42,
"games": 3286,
"wins": 1597,
"advantage": 4.444,
"wr": 0.486,
},
{
"hero_id": 94,
"games": 1070,
"wins": 649,
"advantage": 12.994,
"wr": 0.607,
},
{
"hero_id": 34,
"games": 1171,
"wins": 723,
"advantage": 7.318,
"wr": 0.617,
},
]
ranked = rank_matchup_lists(vs, [], take=3)
self.assertEqual(
[e["hero_id"] for e in ranked["counters"]],
[94, 34, 42],
)
wk = ranked["counters"][2]
self.assertLess(wk["wr"], 0.5)
self.assertGreater(wk["advantage"], 0)
def test_countered_mirrors_lowest_advantage(self) -> None:
vs = [
{"hero_id": 1, "games": 100, "wins": 60, "advantage": 5.0, "wr": 0.6},
{"hero_id": 2, "games": 100, "wins": 40, "advantage": -8.0, "wr": 0.4},
{"hero_id": 3, "games": 50, "wins": 20, "advantage": -3.0, "wr": 0.4},
]
ranked = rank_matchup_lists(vs, [], take=2)
fear = ranked["countered"]
self.assertEqual([e["hero_id"] for e in fear], [2, 3])
self.assertAlmostEqual(fear[0]["advantage"], 8.0)
self.assertAlmostEqual(fear[0]["wr"], 0.6)
def test_synergies_sorted_desc(self) -> None:
with_rows = [
{"hero_id": 10, "games": 10, "wins": 5, "synergy": 1.0, "wr": 0.5},
{"hero_id": 11, "games": 10, "wins": 6, "synergy": 4.5, "wr": 0.6},
]
ranked = rank_matchup_lists([], with_rows, take=2)
self.assertEqual([e["hero_id"] for e in ranked["synergies"]], [11, 10])
class MatchupCacheHelpersTests(unittest.TestCase):
def test_annotate_and_payload_metadata(self) -> None:
cell = annotate_matchup_cell(
{"counters": [{"hero_id": 1}], "countered": [], "synergies": []},
fetched_at="2026-07-28T00:00:00+00:00",
stale=True,
)
self.assertTrue(cell["stale"])
self.assertEqual(cell["fetched_at"], "2026-07-28T00:00:00+00:00")
payload = build_matchup_file_payload(
{"antimage": cell},
take=12,
match_limit=50,
started_at="2026-07-28T00:00:00+00:00",
finished_at="2026-07-28T01:00:00+00:00",
stats={"heroes": 1, "ok": 0, "failed": 1, "stale_kept": 1},
)
self.assertEqual(payload["scope"]["kind"], "global_aggregate")
self.assertIn("global", payload["scope"]["kind"])
self.assertTrue(payload["scope"]["label_zh"])
self.assertEqual(payload["stats"]["stale_kept"], 1)
def test_atomic_write_and_resume_load(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "stratz_matchup_tops.json"
payload = build_matchup_file_payload(
{
"antimage": annotate_matchup_cell(
{"counters": [], "countered": [], "synergies": []},
fetched_at="t0",
)
},
take=12,
match_limit=50,
started_at="t0",
finished_at="t0",
)
write_json_atomic(path, payload)
loaded = load_previous_matchups(path)
self.assertIn("antimage", loaded)
if __name__ == "__main__":
unittest.main()