- 术语表 v1.13:GP 唯一正式命名(删「局内金币」别名)+旗/控制词条更名封印/控制+封印定性由「插旗的对外表达」更正为正式动作名(全库统一、非比喻)+禁用字面从对外命名扩为全库+删「机制文档内部用语不受限」条款+退役词对照表补三行(金币→GP/插旗→封印/旗→封印印记)+危险格词条「被旗控制」→「被封印控制」+B3 豁免例举去旗 - 机检扩容 tools/doc_term_audit.py:RETIRED_TERMS 新增 金币→GP、插旗|标旗→封印 两行(DEFAULT_DIRS 不变,game/ 扫描归代码批);拔旗|撤旗行继任措辞随批换代(插旗不可逆→封印不可逆) - GDD 全域正文换代约 200 行/31 文件:金币→GP(金币袋→GP 袋)、插旗/标旗→封印、雷格/惩罚格→危险格(2026-10-11 退役批存量补扫)、旗概念→封印印记(旗判定→封印判定/标中旗→封印标中/标错旗→标错封印/旗格→封印格/旗位→封印位等复合词系);00-游戏概念「封印降级为类型风味词」定性翻转;修订记录/版本历史/禁令引举/更名记载等留档行零动 - registry/entities.yaml(信标网络可达性/事件序/回执驱动三处)+art 五件(art-bible 封印印记六处/comfyui 背旗→背负封印印记/两清单)+dev 七件(architecture 旗集→封印集/code-conventions-cases/test-conventions/架构图 html json 四件)随批换代 - tools 四脚本注释与图内标注换代(clear_dominance_audit/render_sample_sheet×2/analyze_playtest;代码标识符零动归代码批) - design/qa/代码术语审计报告-2026-10-18.md 随批入库(本批参考素材,06:578 引用闭合 doc_link 死链) - 06-待办清单/术语表两在途脏件(代码术语批 06 登记+A 表头「不用→禁用」)随批一并入库 自检:doc_term_audit --strict 零疑似现行(45 文件 434 命中全留档类);文档域六闸验收通过无新增红(gdd_lint R3 对 00 正文修订注记一次打回已去注记化改写;doc_link 死链经报告入库闭合);正文残留仅 06:73「拔旗」一处(件派生动词白名单豁免语境、机检同款豁免,设计意图记录不动)
87 lines
9.0 KiB
Markdown
87 lines
9.0 KiB
Markdown
# 测试规范(Dungeon Sweeper)
|
||
|
||
> 约束范围:`game/smoke/`、`game/tests/` 与一切场景探针的编写与验收。
|
||
> 分工:测试**执行许可**(什么时候允许跑测试)归 CLAUDE.md「硬性红线·测试执行两入口铁规」;**跑什么闸、什么顺序**归 `tools/run_all_gates.sh`(脚本即清单,本文与 CLAUDE.md 均不另列);本文管测试怎么写、怎么算合格。
|
||
|
||
**写任何测试前必须通读本文。**
|
||
|
||
---
|
||
|
||
## 1. 测试总纲——"存在"必须证明"可达且正确"
|
||
|
||
核心层验收标准通过不算有测试:GDScript 编译不查字典字段与时序,呈现层错误只在运行时暴露。
|
||
测试必须证明功能可达(用户真的能用到)且行为正确(结果符合验收标准)。
|
||
|
||
## 2. 场景级探针标配
|
||
|
||
每新增一个可交互 UI 区域(视图/覆盖层/面板),必须配套场景级 headless 探针:
|
||
真实实例化场景 → 驱动真实输入路径 → 断言可见性与状态。
|
||
|
||
凡模态覆盖层,探针必须断言:打开后自身 visible 且遮挡物已隐藏(模态被遮挡 = 功能存在但不可达)。
|
||
|
||
## 3. 缺陷修复必须沉淀回归断言
|
||
|
||
每个缺陷修复必须在探针或冒烟中留下能抓住该缺陷的断言(例:封印动作耗尽 AP → 必须进入第 2 轮;
|
||
选用道具 → 库存态必须变 Used)。没有回归断言的修复视为未完成。
|
||
|
||
## 4. 提交前全量验证
|
||
|
||
交付前跑 `tools/run_all_gates.sh`(不带 `--quick`)全绿——该脚本是全部验证闸的唯一入口与唯一清单,本文禁另列闸件清单。闸件增减只改脚本。
|
||
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
|
||
|
||
## 5. 测试函数怎么写——验收清单条目的落码规范
|
||
|
||
需求卡片 §7「逐需求点验收清单」每一条都要落成可执行的验证;本文定统一写法,卡里定每批的具体内容(测什么/注入哪里)。写卡期查不出执行载体的条目=不可测,当场呈报,禁拖到实现期。
|
||
|
||
1. **执行载体五选一,逐条声明**:单元测试(`tests/run_all`)/冒烟断言(`smoke_all.gd` 对应场景段)/场景探针(`smoke/` 下 `*_probe`)/MC 同种子逐项比对/人工核对(仅限无法自动化的纪律类需求点,如命名锁定、数值占位)。行为类条目以自动化载体为主。
|
||
2. **粒度与对应关系**:每条清单条目至少一个自动断言;多条条目可合用一个测试函数。断言失败消息末尾带编号尾缀〔卡短名 Vn〕(如〔秘宝批 V3〕)——断言与卡片清单可互相 grep 查找。
|
||
3. **断言词汇按验证对象五选一**:
|
||
|
||
| 词汇 | 适用场景 |
|
||
|---|---|
|
||
| 逐位相等 | 同种子下确定性公式与结算的精确逐项比对 |
|
||
| 区间/差值带 | 概率与平衡读数(MC 同种子配对比较,出带即红) |
|
||
| 快照比对 | 存档域结构、配置表行结构 |
|
||
| 重放 | 同种子断点回放、改前改后配对 |
|
||
| 状态/计数器断言 | 条件解锁、限次、充能——置数据→走路径→断计数值 |
|
||
|
||
4. **调试注入两层(能力测试与流程体验两分法的落码面)**:自动化测试=测试代码直调核心层写口构造状态(直改数据表行/计数器/存档域,不经 UI、不走正常资源积累流程——冒烟现役做法);人工体验=DebugOverlay/DS_DEBUG 调试面,服务用户目检。清单条目的「怎么测」必须写到数据面粒度:改哪张表哪行、置哪个计数、调哪个核心写口。
|
||
5. **换代批旧验证约束同生死**:删除旧数据行/旧实现代码的批次,必须同批摘除只验证旧实现的断言与护栏校验,由新断言替代——旧件断言残留=冒烟假绿来源;合并后冒烟全绿且全仓无旧件残留引用为证。
|
||
|
||
## 6. 变异验证——验收函数的拦截能力自证
|
||
|
||
测试绿只证明「当前代码没犯这个错」,不证明「犯了这个错会被抓住」。新增或改写的验收函数(冒烟断言/探针自检/闸机判据)必须配一次变异验证,把拦截能力自证一遍。**无变异红记录的断言不写「已验收」,只写「已实现,拦截能力未证」。**
|
||
|
||
**操作四步(逐条落实现报告变异验证记录表)**:
|
||
|
||
1. **注入**——把被测件改坏成该类缺陷的最小形态(翻装配序、注释一行 `add_child`、把状态源取反、把层 `visible` 置 false)。一次只注入一处;可直接改源码,不必留长期开关。
|
||
2. **跑最窄的那一道闸**——只跑能覆盖该断言的最小单元(单冒烟脚本/单探针/单比对命令),禁跑全套闸(见 process-conventions §6 闸机轮次纪律)。判据:注入后该断言**必须变红**;红在别处而目标断言仍绿=判据没打在缺陷上,按第 4 条处理。
|
||
3. **精确还原**——`git checkout -- <文件>`(不用 `git stash`、不手工回改,防残留)。还原后复跑同一道闸确认回绿,才算本轮闭环。
|
||
4. **记录**——变异点(文件:行)、跑的闸、红输出摘要、还原结论,逐条进实现报告记录表。
|
||
|
||
**变异不红怎么办(二选一,不许含糊带过)**:
|
||
|
||
- **改判据**——把断言打到真正的缺陷面上(例:断言「菜单标题可见」只查截图墨色占比时,把菜单层藏起来仍不红——底层棋盘透过标题框照样给出高反差像素;改查 `is_visible_in_tree` 或加 golden 逐像素比对才红)。
|
||
- **如实标注拦截边界**——判据本身只覆盖弱面的(如「只证伪整框空白/整框糊,不证明框里是何内容」),在断言注释与报告里写明边界,并说明强判据由哪一件承担。
|
||
|
||
**判据强弱分层**:同一缺陷面往往需要多件配合——**可见性/状态源类**缺陷由 `is_visible_in_tree`、树序、状态源取值的**运行期断言**抓;**内容/观感类**缺陷由 **golden 逐像素比对**抓;**占比/统计类**判据(墨色占比、纹理幅度)只能兜「整框空白/整框糊/压 busy 纹理」,是补充不是主力。写卡时按此分层配齐,别指望一条断言包打。
|
||
|
||
## 7. 判定三硬闸——闸承载的构造义务(迭代 29 三硬闸 2026-10-17 用户裁升格为纪律)
|
||
|
||
任何**新增或改写的闸承载**(闸脚本/批跑编排/探针入口)必须三闸齐备;现行各闸状态登记归架构文档「测试与质量域」节(本文不另列闸件清单):
|
||
|
||
1. **退出码为唯一权威判据**——输出里的 PASS 串只作附加判据不作判据主体;打印 PASS 后 `quit(1)` 必须判红。
|
||
2. **SCRIPT ERROR / Parse Error 扫描面在位**——GDScript 脚本错误不改进程退出码、不计失败数(机制事实见 §8),错误标记必须扫输出,且判据必须覆盖「跑了但半途脚本错误」态——退出码 0 但输出缺预期签名同样判红(防静默退出)。
|
||
3. **断言数下限**——零断言的正常返回与断言失败必须区分开(现行做法:`Kit.finish` 零断言返回专用退出码 2,不与「断言失败=1」混用,否则致命类套件的期望码协议会放过空跑)。
|
||
- 负面套件(测试目标就是产生错误输出)仅可豁免第 2 闸,且须在 manifest 显式标记,其余两闸照判。
|
||
- 子进程输出须经系统命令解释器重定向落盘再读——`OS.execute` 的输出管道在本机恒空。
|
||
|
||
**新写测试件全类型标注**(2026-10-17 用户裁写法纪律)——新写的测试件(冒烟断言/探针/单测)参数、返回值、容器一律带类型标注,与 S9 对产品码的要求同型;存量不强制清扫,被批次触碰时顺带换代。暂不机器闸(S9 扫描面=产品码,smoke/tests 豁免是测量面直构惯例的既有裁量)。
|
||
|
||
## 8. 判定可靠性优先于覆盖率(迭代 29 核心命题 2026-10-17 用户裁成节)
|
||
|
||
- 「跑一遍没崩=通过」无效:测试绿只证明**当前代码没犯这个错**,不证明**犯了这个错会被抓住**;断言存在不等于断言执行。
|
||
- **脚本错误会静默中断所在函数的剩余断言,而套件仍报全绿**(机制事实):GDScript 无脚本错误陷阱 API,错误不改进程退出码、不计失败数。三处实证:①2026-09-19「309 项 0 失败」实为断言未跑全(状态记录 83);②敌人表行集纪律 10 条断言因定型数组赋值错误从未执行(迭代 29 修复后两条正向见红=夹具本缺锚行);③`Callable` 形参类型写错致解析函数返回 null、后续断言整段蒸发。
|
||
- 由此产生两条义务:**写闸件**按 §7 配三硬闸;**写验收函数**必须自证断言全数执行——变异验证(§6)为主证,反例实证(构造缺陷态改前判绿/改后判红)与零命中自检(扫描面为空即判红)为辅证。
|
||
- **覆盖率不是目标**:行覆盖率度量缺失(Godot 无内建,第三方属新基建,是否引入 06 在册待裁);现行补洞=零指名单测清单+人工判定,判定可靠性靠上列自证手段,不靠覆盖率数字。
|