feat: update tester

This commit is contained in:
2026-09-16 14:40:33 +08:00
parent 2783946cec
commit bdfd2ff342
8 changed files with 259 additions and 22 deletions
+42 -6
View File
@@ -20,7 +20,11 @@ except ImportError: # pragma: no cover
raise SystemExit(2)
SURFACES = ("script", "browser", "mobile")
STATUSES = ("active", "retired")
STATUSES = ("active", "retired", "pending")
STATUS_SKIP_REASON = {
"retired": "retired",
"pending": "pending(暂缓,见 notes)",
}
SUITES = ("smoke", "full", "slow")
CANONICAL_RISKS = ("safe", "act", "harm")
RESULTS = ("pass", "fail", "environment-fail", "skipped")
@@ -86,6 +90,27 @@ def case_files(root: Path) -> list[Path]:
return sorted(p for p in d.glob("*.yaml") if p.is_file())
def category_rank(root: Path) -> dict[str, int]:
path = catalog_dir(root) / "catalog.yaml"
order: list[str] = []
if path.is_file():
data = load_yaml(path) or {}
if isinstance(data, dict):
for item in data.get("categories") or []:
if isinstance(item, dict) and item.get("id"):
order.append(str(item["id"]))
return {name: index for index, name in enumerate(order)}
def sort_by_catalog(root: Path, cases: list[dict[str, Any]]) -> list[dict[str, Any]]:
rank = category_rank(root)
for case in cases:
cat = str(case.get("category") or "")
if cat and cat not in rank:
rank[cat] = len(rank)
return sorted(cases, key=lambda case: rank.get(str(case.get("category") or ""), 999))
def load_all_cases(root: Path) -> list[dict[str, Any]]:
out: list[dict[str, Any]] = []
for path in case_files(root):
@@ -108,7 +133,7 @@ def load_all_cases(root: Path) -> list[dict[str, Any]]:
item["_file_category"] = cat
item["_file_title"] = title
out.append(item)
return out
return sort_by_catalog(root, out)
def resolve_vars(root: Path, meta: dict[str, Any]) -> dict[str, str]:
@@ -189,7 +214,8 @@ def cmd_list(root: Path) -> int:
cats_meta = {c["id"]: c for c in meta.get("categories") or [] if isinstance(c, dict) and "id" in c}
active = [c for c in cases if c.get("status", "active") == "active"]
retired = [c for c in cases if c.get("status") == "retired"]
print(f"## 测试目录 active {len(active)} / retired {len(retired)}")
pending = [c for c in cases if c.get("status") == "pending"]
print(f"## 测试目录 active {len(active)} / pending {len(pending)} / retired {len(retired)}")
print()
headers = ["分类", "标题", "条数", "smoke"] + risks + list(SURFACES)
print("| " + " | ".join(headers) + " |")
@@ -222,6 +248,9 @@ def cmd_list(root: Path) -> int:
code = run_export_csv(root)
if code == 0:
print(f"清单: {catalog_dir(root).relative_to(root) / 'cases.csv'}")
run_csvs = sorted((catalog_dir(root) / "runs").glob("*.csv"))
if run_csvs:
print(f"成绩单: {run_csvs[-1].relative_to(root)}")
return code
@@ -249,7 +278,11 @@ def cmd_select(args: argparse.Namespace, root: Path) -> int:
cid = str(case.get("id") or "")
if case.get("status", "active") != "active":
if cid in wanted:
skipped.append({"id": cid, "reason": "retired"})
status = str(case.get("status"))
skipped.append({
"id": cid,
"reason": STATUS_SKIP_REASON.get(status, status),
})
missing.discard(cid)
continue
if wanted:
@@ -450,7 +483,8 @@ def cmd_validate(root: Path) -> int:
return 1
cases = load_all_cases(root)
active = sum(1 for c in cases if c.get("status", "active") == "active")
print(f"✓ validate 通过 active={active} total={len(cases)}")
pending = sum(1 for c in cases if c.get("status") == "pending")
print(f"✓ validate 通过 active={active} pending={pending} total={len(cases)}")
return 0
@@ -504,7 +538,9 @@ def cmd_run_script(root: Path, case_id: str) -> int:
return 2
public_id = case.get("id")
if case.get("status") != "active":
print(json.dumps({"id": public_id, "result": "skipped", "evidence": "retired"}, ensure_ascii=False))
status = str(case.get("status"))
reason = STATUS_SKIP_REASON.get(status, status)
print(json.dumps({"id": public_id, "result": "skipped", "evidence": reason}, ensure_ascii=False))
return 0
if case.get("surface") != "script":
print(