feat: restore source parity and harden agent runtime
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Golden Test:用 JSON fixture 回归报表 transform 流水线关键输出。
|
||||
后续可追加 JNPF 导出的样例 fixture 做对比。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from online_dev.report_manager.engine.convert import transform
|
||||
from online_dev.report_manager.engine.dataset_transform import transform_dataset_rows
|
||||
|
||||
_FIXTURES_DIR = Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
def _load_fixture(name: str) -> dict:
|
||||
path = _FIXTURES_DIR / name
|
||||
with open(path, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def _cell_v(snapshot: dict, sheet_id: str, row: int, col: int) -> str:
|
||||
sheet = (snapshot.get("sheets") or {}).get(sheet_id) or {}
|
||||
cell = (sheet.get("cellData") or {}).get(str(row), {}).get(str(col), {})
|
||||
v = cell.get("v")
|
||||
return "" if v is None else str(v)
|
||||
|
||||
|
||||
def _prepare_datasets(fixture: dict) -> Dict[str, List[Any]]:
|
||||
raw = fixture.get("datasets") or {}
|
||||
field_mapping_root = fixture.get("field_mapping") or {}
|
||||
version_convert = fixture.get("convert_config")
|
||||
out: Dict[str, List[Any]] = {}
|
||||
for alias, rows in raw.items():
|
||||
mapping = field_mapping_root.get(alias) if isinstance(field_mapping_root, dict) else field_mapping_root
|
||||
out[alias] = transform_dataset_rows(
|
||||
rows,
|
||||
field_mapping=mapping,
|
||||
version_convert=version_convert,
|
||||
alias=alias,
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def _values_match(expected: Any, actual: str, *, tolerance: float = 1e-6) -> bool:
|
||||
if expected == actual:
|
||||
return True
|
||||
try:
|
||||
exp_f = float(expected)
|
||||
act_f = float(actual)
|
||||
return math.isclose(exp_f, act_f, rel_tol=tolerance, abs_tol=tolerance)
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
|
||||
|
||||
def _run_golden_fixture(fixture: dict) -> None:
|
||||
datasets = _prepare_datasets(fixture)
|
||||
out = transform(
|
||||
fixture["snapshot"],
|
||||
fixture.get("cells") or {},
|
||||
datasets,
|
||||
fixture.get("params") or {},
|
||||
column_list=fixture.get("column_list"),
|
||||
fence_list=fixture.get("fence_list"),
|
||||
)
|
||||
failures: List[str] = []
|
||||
for sheet_id, cells in (fixture.get("expect") or {}).items():
|
||||
for addr, expected in cells.items():
|
||||
row_s, col_s = addr.split(",", 1)
|
||||
actual = _cell_v(out, sheet_id, int(row_s), int(col_s))
|
||||
exp_str = "" if expected is None else str(expected)
|
||||
if not _values_match(exp_str, actual):
|
||||
failures.append(
|
||||
f" {sheet_id}!{addr}: expected {exp_str!r}, got {actual!r}"
|
||||
)
|
||||
if failures:
|
||||
name = fixture.get("name") or "unnamed"
|
||||
msg = f"{name} failed ({len(failures)} cell(s)):\n" + "\n".join(failures)
|
||||
raise AssertionError(msg)
|
||||
|
||||
|
||||
def test_golden_list_down():
|
||||
_run_golden_fixture(_load_fixture("golden_list_down.json"))
|
||||
|
||||
|
||||
def test_all_golden_fixtures():
|
||||
for path in sorted(_FIXTURES_DIR.glob("golden_*.json")):
|
||||
_run_golden_fixture(_load_fixture(path.name))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_all_golden_fixtures()
|
||||
print(f"ok ({len(list(_FIXTURES_DIR.glob('golden_*.json')))} fixtures)")
|
||||
Reference in New Issue
Block a user