""" 为 title_styler 回归测试结果生成一个零依赖前端 (viewer.html)。 工作流: PYTHONPATH=. python tests/title_styler_regression/run.py --run baseline PYTHONPATH=. python tests/title_styler_regression/run.py --run after_fix PYTHONPATH=. python tests/title_styler_regression/viewer.py # 然后浏览器打开 tests/title_styler_regression/viewer.html 特性: - 扫描 results//summary.json 自动发现所有 run - 顶部两个 dropdown 选 左/右 run, 一键切换 - 每个 case 一行: 左 PNG | 右 PNG | meta (尺寸、字号、dh) - 支持按 |dh| 排序、按模板名 / test_id 过滤 - 仅生成一个 HTML 文件 (相对路径引用 PNG), file:// 协议可直接打开 """ import base64 import json import os import sys ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) HERE = os.path.abspath(os.path.dirname(__file__)) RESULTS_ROOT = os.path.join(HERE, "results") OUT_HTML = os.path.join(HERE, "viewer.html") def discover_runs(): runs = {} if not os.path.isdir(RESULTS_ROOT): return runs for entry in sorted(os.listdir(RESULTS_ROOT)): run_dir = os.path.join(RESULTS_ROOT, entry) summary_path = os.path.join(run_dir, "summary.json") if not os.path.isfile(summary_path): continue with open(summary_path, encoding="utf-8") as f: summary = json.load(f) cases = {} for c in summary.get("cases", []): cid = c.get("case_id") if not cid: continue png_rel = os.path.relpath( os.path.join(run_dir, cid, "title.png"), start=HERE ) svg_rel = os.path.relpath( os.path.join(run_dir, cid, "title.svg"), start=HERE ) png_exists = os.path.isfile(os.path.join(HERE, png_rel)) cases[cid] = { "ok": c.get("ok", False), "reason": c.get("reason"), "png": png_rel if png_exists else None, "svg": svg_rel, "w": c.get("svg_width"), "h": c.get("svg_height"), "fonts": c.get("font_size_hist", {}), "test_id": c.get("test_id"), "template": c.get("template_name"), "title": c.get("title_segments"), "description": c.get("description"), } runs[entry] = { "n_ok": summary.get("n_ok", 0), "n_fail": summary.get("n_fail", 0), "cases": cases, } return runs HTML_TEMPLATE = """ title_styler regression viewer

title_styler regression viewer

""" def main(): runs = discover_runs() if not runs: print("no run found under tests/title_styler_regression/results/", file=sys.stderr) print("first run:", file=sys.stderr) print(" PYTHONPATH=. python tests/title_styler_regression/run.py --run baseline", file=sys.stderr) payload = json.dumps(runs, ensure_ascii=False) html = HTML_TEMPLATE.replace("__RUNS_JSON__", payload) with open(OUT_HTML, "w", encoding="utf-8") as f: f.write(html) print(f"wrote {OUT_HTML}") if runs: print("available runs:") for name, r in runs.items(): print(f" - {name} ok={r['n_ok']} fail={r['n_fail']}") print(f"\nopen in browser: file://{OUT_HTML}") if __name__ == "__main__": main()