Files
AgentLab/backend/tests/test_frontend_eval_unions.py
T
ThearchyHelios 78252fdfa2 测试:评测页的前端取值和服务端常量逐个对上(tests/test_frontend_eval_unions.py)
typesEval.ts 的联合类型(状态、发起方式、题目种类、结论、作答路径、期望种类、期望答案来源、升版处置、试算结论、各期望的结论、
转移、归因、目录视图、E1/E3 档位)和 termsEval.ts 里对应的叫法表,直接读文件和 app/eval、app/core/job_runtime、api/evals 的常量比:
服务端加了一种(比如作答路径「被驳回」)前端没跟上,界面会写出英文原值;同 test_frontend_type_unions.py 的写法,另开一个文件
免得和别的包改同一个文件。
2026-10-16 20:46:18 +08:00

96 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""评测页的前端约定(frontend/src/typesEval.ts)和文案(lib/termsEval.ts 的 EVAL_TEXT)里的取值,和服务端的常量逐个对上。
评测页上的结论、作答路径、转移、归因、目录视图、状态都是服务端给的取值,前端照着写叫法(界面层不放逻辑,叫法在 termsEval)。
服务端加了一种(比如作答路径「被驳回」),前端的联合类型和叫法表没跟上,界面就写出英文原值;前端多写了一种,就在等一个
永远不会来的值。这里直接读两份 .ts 文件比(同 test_frontend_type_unions.py 的写法),改了一边没改另一边就过不去。
"""
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
TYPES_EVAL = ROOT / "frontend" / "src" / "typesEval.ts"
TERMS_EVAL = ROOT / "frontend" / "src" / "lib" / "termsEval.ts"
_COMMENT = re.compile(r"/\*.*?\*/|//[^\n]*", re.S)
def _source(path: Path) -> str:
return _COMMENT.sub("", path.read_text(encoding="utf-8"))
def _union(name: str) -> list[str]:
text = _source(TYPES_EVAL)
found = re.search(rf"export type {name} =(.*?)(?=\nexport |\n\n|\Z)", text, re.S)
assert found is not None, f"typesEval.ts 里没有 export type {name}"
return re.findall(r"'([^']+)'", found.group(1))
def _labels(path: str) -> list[str]:
"""EVAL_TEXT 里某一张叫法表(a.b 这样的路径)的键,按写的顺序。只认一行写完、或几行写完的对象字面量。"""
text = _source(TERMS_EVAL)
*parents, leaf = path.split(".")
start = 0
for part in parents:
hit = re.search(rf"\n\s*{part}: \{{", text[start:])
assert hit is not None, f"EVAL_TEXT 里没有 {part}"
start += hit.end()
hit = re.search(rf"\n\s*{leaf}: \{{(.*?)\}}( as Record<[^>]+>)?,", text[start:], re.S)
assert hit is not None, f"EVAL_TEXT 里没有 {path}"
return re.findall(r"(\w+): '", hit.group(1))
def test_statuses_triggers_and_kinds():
from app.core.job_runtime import ACTIVE, FINISHED
from app.db.models_eval import CASE_KINDS, RESULT_PATHS, RUN_TRIGGERS, VERDICTS
assert _union("EvalStatus") == [*ACTIVE, *FINISHED]
assert _union("EvalTrigger") == list(RUN_TRIGGERS)
assert _union("EvalCaseKind") == list(CASE_KINDS)
assert _union("EvalVerdict") == list(VERDICTS)
assert _union("EvalPath") == list(RESULT_PATHS)
assert _labels("status") == [*ACTIVE, *FINISHED]
assert _labels("trigger") == list(RUN_TRIGGERS)
assert _labels("verdict") == list(VERDICTS)
assert _labels("path") == list(RESULT_PATHS)
def test_expectations_gold_and_trial():
from app.eval.cases import EXPECTATION_KINDS, GOLD_KINDS
from app.eval.gold import STATUSES, UPGRADE_LABEL
assert _union("EvalExpectationKind") == list(EXPECTATION_KINDS)
assert _labels("expectation.kind") == list(EXPECTATION_KINDS)
assert _union("EvalGoldKind") == list(GOLD_KINDS)
assert _labels("gold.kind") == list(GOLD_KINDS)
assert _union("EvalUpgradePolicy") == list(UPGRADE_LABEL)
# 试算的结论:服务端的几种,加上作答前后算出来不一样时的 drifted(gold.settle)
assert set(STATUSES) | {"drifted"} == set(_union("EvalTrialStatus"))
assert set(_union("EvalTrialStatus")) <= set(_labels("trialStatus"))
def test_scores_compare_and_catalog_modes():
from app.eval.compare import CAUSES, TRANSITIONS
from app.eval.score import OUTCOMES, TEXT_OUTCOMES
from app.eval.variants import CATALOG_MODES
assert _union("EvalOutcome") == list(OUTCOMES)
assert _labels("outcome") == list(OUTCOMES)
assert _union("EvalTextOutcome") == list(TEXT_OUTCOMES)
assert _labels("textOutcome") == list(TEXT_OUTCOMES)
assert _union("EvalTransition") == list(TRANSITIONS)
assert _labels("compare.transition") == list(TRANSITIONS)
assert _union("EvalCause") == list(CAUSES)
assert _labels("compare.cause") == list(CAUSES)
assert _union("EvalCatalogMode") == list(CATALOG_MODES)
assert _labels("start.catalogMode") == list(CATALOG_MODES)
def test_signal_bands_follow_the_server():
from app.api.evals import SIGNAL_CRITERIA
assert _union("EvalE1Band") == [c["band"] for c in SIGNAL_CRITERIA["e1"]]
assert _union("EvalE3Band") == [c["band"] for c in SIGNAL_CRITERIA["e3"]]
assert set(_labels("signals.band")) == {c["band"] for c in [*SIGNAL_CRITERIA["e1"], *SIGNAL_CRITERIA["e3"]]}