Files
.pouch/skills/tester/references/concepts.md
T
laily cc9af04a40 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)同步更新。
2026-09-16 23:07:08 +08:00

8.6 KiB
Raw Blame History

tester 概念、命名与设计理由

这是 tester 的唯一术语真相。写用例、改脚本、看文档遇到词义冲突时,以本文件为准。

0. 三层结构

catalog(整个测试集)
└── category(= 一个 suite,一个 cases/<cat>.yaml)
    └── case(一条用例)
层 是什么 业界对应
catalog 全部用例 + 全局配置(catalog.yaml) pytest 的一次 collection;整个 test suite
category 一组用例 + 自己的前置条件(status_probe) Robot suite;pytest 一个目录 + conftest.py
case 一条用例 test case

「suite」只作总称(泛指整个测试集),不作 YAML 键。集合级的角色由 category 承担:cases/<cat>.yaml 就是 suite 容器,categories[].status_probe 就是 Suite Setup。所以框架里没有 suite 字段。

1. 术语表

每个词一句话定义 + 业界锚点 + 「它不是什么」。

用例字段

词 定义 业界锚点 不是什么
case 一条可独立判定的测试 test case 不是一次运行记录(那是 runs/)
tag 成本档:smoke / full / slow,单选 pytest mark;JUnit / Robot tag 不是分类,不是「一个 suite」
risk 执行副作用等级:readonly / mutating / destructive read-only vs mutating;destructive tests;K8s e2e [Disruptive] 不是概率,不是「要不要人」(那是 automation)
lifecycle 用例生命周期:active / pending / retired JUnit @Disabled;pytest skip / deselect 不是 HTTP 状态,不是前置探测(那是 api-status / status_probe)
driver 谁来驱动执行:script / browser / mobile Selenium / Appium driver 不是「要不要人」(那是 automation)
automation 人工参与度:automated / assisted / manual TestRail Automation Type;ADO Automation status;Xray Test Type 不是执行器(那是 driver)
session 可复用会话(浏览器 / 模拟器) pytest fixture;Robot suite variable 不是一条用例
gate 项目细分闸门名 → 环境变量(motion / hardware / weld) 授权开关 不是 risk,不要拿它代替风险等级
authorize 风险档 → 环境变量。该档执行前必须为 true pytest skipif 条件 不是认证(auth),是授权
assume 额外跳过条件(gate / authorize 之外的环境表达式) JUnit assumeTrue;pytest skipif 不是授权开关的重复写法
status_probe 分类级前置条件:请求一个 URL,命中即视为前置不满足 pytest session fixture;Robot Suite Setup 不是产品失败,不是整轮硬闸
how 怎么测:steps / run / url / timeout test steps 不是判定标准
expected 怎么算过:{kind, value} 列表 pytest assert;Robot Should … 不是步骤
run_together 必须成组执行的用例(有序、可选 continue_on_fail) 场景组(scenario) 不是 suite,不是 tag

结果词

结果 定义 业界锚点
pass 通过 passed
fail 产品缺陷 failed
environment-fail 前置/环境导致无法执行,永远不是产品失败 pytest error;JUnit aborted
skipped 主动不跑:retired / pending / 超风险上限 / 未授权 / assume 不成立 pytest skipped;JUnit disabled
not-run 被动没轮到:失败即停后剩下的;分类被 status_probe 挡住整组没执行;automation 需人工而无人值守 pytest not run;deselected

2. 命名迁移对照(v1 → v2)

v1 v2 为什么改
用例 status lifecycle v1 的 status 一词三义:用例状态、api-status 的 HTTP 状态、status_probe。拆开后各是各的
用例 suite tag Robot 里 suite 是集合,cases/<cat>.yaml 才是集合;我们却拿它当标记。改 tag 与 pytest mark / JUnit tag 对齐
用例 surface driver surface 是自造词;driver 是 Selenium / Appium 的既有概念,且正好回答「谁来驱动」
用例 cleanup teardown 与 pytest teardown / JUnit @AfterEach / Robot [Teardown] 对齐
用例 skip_unless assume 语义是「假设成立才跑」,对应 JUnit assumeTrue;旧名与 gate 含义重叠
用例 requires 删除 只出现在导出的 CSV,不参与任何逻辑;126 条标注还不一致。前置能力改用 tag + driver + gate/assume 表达
catalog auth_env authorize auth 被读成「认证」,实际是「授权放行」
risk 值 safe/act/harm readonly/mutating/destructive act 太含糊(谁都在 act),harm 情绪化,且把「改了状态」与「难恢复」混成一维。新词是单调三级,见下
结果 skipped(含被动) skipped + not-run v1 把「主动不跑」和「被动没轮到」混在一个词里,成绩单看不出是哪种

3. 关键设计理由(为什么是这些值)

3.1 risk:为什么是 readonly / mutating / destructive

  • 这一维回答的是「跑它会不会改变被测系统、有多难退回」,不是概率,也不是「要不要人」。
  • readonly / mutating 是数据库、文件系统、API 测试里的通用二分,事实性描述。
  • destructive 是硬件 / 内核 / 集群测试的标准词(Kubernetes e2e 用 [Disruptive] 标记会打断集群的用例)。
  • 三级单调:readonly ⊂ mutating ⊂ destructive,所以只需要一个上限 default_max_risk 和一个 --max-risk,不用组合矩阵。
  • 与 gate 正交:risk 说「影响多大」,gate 说「碰哪个子系统」。点动 vs 焊接这种细分授权用 gate,不要再造 risk 名。
  • tag=smoke 只能配 risk=readonly:冒烟测试不许留下变化。

3.2 automation:为什么是 automated / assisted / manual

  • 有些用例无法自动化,或需要人在现场配合(急停、断电、物理复位、目视 LED)。这需要在选范围阶段就能筛出来。
  • 这是测试管理工具的标准字段(TestRail Automation Type、ADO Automation status、Xray Test Type),因此沿用 automation 这个名字。
  • 与 driver 正交:driver 说「用什么驱动」,automation 说「要不要人」。把 manual 塞进 driver 就无法表达 assisted(它仍由 script/browser 驱动)。
  • 三档的含义与约束:
    • automated(默认):Agent 端到端跑完。
    • assisted:Agent 驱动,但至少一步需要人在场;该步在 how.steps 里以 [人工] 开头(可被 validate 机器判定)。
    • manual:只能人工执行;禁止 driver、禁止 how.run,必须有 how.steps。
  • 默认只跑 automated。无人值守时 assisted / manual 记 not-run;有人在场时 assisted 暂停等人确认,manual 由人工回报结果。

3.3 结果为什么拆出 not-run

  • skipped = 我们决定不跑(retired / pending / 超上限 / 未授权 / assume 不成立)。
  • not-run = 没轮到(失败即停后剩下的 / 分类被前置挡住 / 需人工而无人值守)。
  • 混在一起,成绩单就看不出「本轮到底跑没跑」。拆开后 executed 列(yes / no)与原因都清楚。

3.4 status_probe 为什么是分类级

  • 不同分类的前置条件不同:相机链路走 API_BASE(8095) / 相机内网,独立于机械臂 FSM(8096)。机械臂没连上不应该挡住相机测试。
  • 因此它是分类级前置条件:catalog.status_probe 是全局默认,categories[].status_probe 可覆盖(缺省继承 / false 关闭 / mapping 整体替换)。对应 pytest 的 session fixture、Robot 的 Suite Setup。
  • 命中或不可达只影响用它的分类;只有所有选中分类都被挡住,整轮结论才是 environment-fail。select 会按分类返回解析后的生效值,Agent 不要自己读 catalog 猜。

4. 不采用的词

词 不用它的原因
suite(作字段) 与 Robot 的「集合」语义冲突;集合角色已由 category 承担
status(作字段) 与 HTTP 状态、前置探测撞词
surface 自造词,业界无此概念
requires 不参与逻辑,标注还容易失真
sanity / regression / acceptance 与 smoke / full 分不清,且已有 category / id / risk / automation 多层筛选
preconditions(通用列表) 当前只有 status_probe 一种前置,出现第二种再抽象