tester v2: 术语对齐 pytest/JUnit/Robot,补齐 automation 与 not-run

字段改名(每项取舍的理由见新增的 references/concepts.md):
- 用例 status -> lifecycle, suite -> tag, surface -> driver,
  cleanup -> teardown, skip_unless -> assume;删除 requires
- risk 取值 safe/act/harm -> readonly/mutating/destructive(单调三级,
  与 gate 正交)
- catalog auth_env -> authorize;授权变量统一为
  AUTHORIZE_MUTATING / AUTHORIZE_DESTRUCTIVE

新增用例字段 automation(automated/assisted/manual),默认 automated,
并在 validate 里机器校验:manual 禁用 driver 与 how.run 且必须有
how.steps;assisted 至少一步以 [人工] 开头。select 新增 --automation。

结果词新增 not-run,区分「主动不跑」(skipped:retired/pending/超风险
上限/未授权/assume 不成立)与「没轮到」(失败即停后、被分类前置挡住整组、
需人工而无人值守)。

status_probe 定为分类级前置条件:catalog 顶层为默认,categories[] 同名键
覆盖(缺省继承 / false 关闭 / mapping 整体替换)。select 按分类返回生效值,
并把 probe.url 用 vars 展开(solve Agent 无法自行解析 ${VAR} 的问题),
同批返回 vars 供 how 里的 ${...} 替换。

新增 references/concepts.md:术语表(每词一句唯一定义 + 业界锚点 +
反例)、v1->v2 映射、以及 risk/automation/not-run/status_probe 的设计理由。
其余文档(SKILL/README/schema/levels/run/maintain)与三个脚本(catalog、
generate_cases_csv、generate_run_csv)同步更新。
This commit is contained in:
2026-09-16 23:07:08 +08:00
parent ca3156ed93
commit cc9af04a40
12 changed files with 443 additions and 143 deletions
+7 -6
View File
@@ -18,8 +18,9 @@ except ImportError: # pragma: no cover
from generate_cases_csv import load_cases, one_line, resolve_root, tester_dir
RESULTS = ("pass", "fail", "environment-fail", "skipped")
RESULTS = ("pass", "fail", "environment-fail", "skipped", "not-run")
EXECUTED_YES = frozenset({"pass", "fail", "environment-fail"})
EXECUTED_NO = frozenset({"skipped", "not-run"})
FIELDS = (
"id",
"result",
@@ -28,9 +29,9 @@ FIELDS = (
"notes",
"category",
"title",
"suite",
"tag",
"risk",
"surface",
"driver",
"maps_to",
)
@@ -38,7 +39,7 @@ FIELDS = (
def executed_cell(result: str) -> str:
if result in EXECUTED_YES:
return "yes"
if result == "skipped":
if result in EXECUTED_NO:
return "no"
return ""
@@ -115,9 +116,9 @@ def export_run_csv(
"notes": one_line(item.get("notes")),
"category": case.get("category") or "",
"title": case.get("title") or "",
"suite": case.get("suite") or "",
"tag": case.get("tag") or "",
"risk": case.get("risk") or "",
"surface": case.get("surface") or "",
"driver": case.get("driver") or "",
"maps_to": case.get("maps_to") or "",
}
)