Axıs
技能目录

24 · 可测试性与自动化验证

24 · 可测试性与自动化验证

核心命题:系统必须能被自动化验证,而不是靠人肉试玩。 小团队没有 QA 部门,唯一出路是让系统"自己证明自己是对的"。 相关:systems/08(蒙特卡洛与机器人跑测)、systems/09(平衡工作流)。

1. 可测试性是设计属性,不是事后补的

如果系统无法被测试,那是设计问题,不是测试问题。

设计原则 做法 反面
确定性 同样的输入 + 同样的种子 = 同样的输出 依赖帧率、随机无种子、时间依赖
参数外置 所有数值在外部数据源 魔数散落在代码里
可观测 任何系统状态可被查询/打印 状态只在内部,只能靠眼睛看
可注入 能注入假输入、假时间、假随机 强耦合到引擎/UI
可跳过 能跳过表现层,只跑逻辑 逻辑与动画绑定(跑测试要等动画)
无副作用 同样的操作可重复执行 全局单例状态污染

最快收益的两条:确定性 + 参数外置。有了这两条,90% 的自动化才可能。

2. 三层测试金字塔

层 测什么 成本 数量 频率
L1 逻辑单元测试 单条公式/规则 极低 多(数百) 每次提交
L2 系统模拟测试 完整循环、经济、平衡 中 中(数十) 每次构建
L3 集成与人工 手感、体验、可读性 高 少 每迭代

关键判断:凡是能用代码验证的,绝不靠人看。

  • 能自动化:数值范围、可解性、经济守恒、约束违反、回归
  • 只能人工:手感、情绪、可读性、乐趣

L1 示例(应写成自动化断言):

assert damage(level=1, weapon=base) == 10
assert damage(level=100, weapon=base) < damage(level=100, weapon=epic)
assert dr(armor=0) == 0 and dr(armor=K) == 0.5   // 半效点
assert ehp(hp=100, armor=K) == 200                // EHP 线性

3. 模拟 Harness(最重要的投资)

定义:一个不渲染、只跑逻辑的测试环境,让机器人以 N 倍速玩你的游戏。

能力 用途
无头运行 跳过渲染/动画,10–1000× 速
脚本化策略 机器人按"最优/随机/贪心/新手"策略玩
批量跑 一次跑 10⁴ 局
数据导出 每局的资源曲线、通过率、build、死亡点
种子固定 版本对比时可复现

三种机器人策略(至少实现前两种):

策略 用途
最优 找出理论上限与支配策略
随机 测下限,找"必死局"
新手模拟 按新手行为模式(选第一个/不探索)测 FTUE

投资回报:harness 的建设成本通常 3–10 人日,但能替代数百小时的试玩。 卡牌/自走棋/自动化类游戏必须做——组合空间人手测不完。

4. 回归测试与黄金数据(Golden Run)

问题:改了一个数值,怎么知道没破坏别的东西?

做法:记录一份"黄金数据"(基准结果),每次构建后重跑并对比差异。

golden_run_v1.3.json
  平均 TTK: 4.2s
  通关率:  36%
  平均单局时长: 24min
  各 build 使用率: [...]
  资源存量@10h: {...}

对比规则:

  • 差异 < 5% → 通过
  • 差异 5–15% → 警告,人工确认是否符合预期
  • 差异 > 15% → 失败,必须解释(预期内改动需更新黄金数据)

黄金数据必须带版本标签,并在有意改动后主动更新(而不是被绕过)。

5. 平衡自动化扫描

每次构建自动跑一遍,输出三张表的红项(见 systems/09 §2):

扫描 自动判定
使用率扫描 使用率 >60% → 支配策略; <5% → 废卡
通过率扫描 任何关卡 <20% 或 >90% → 断崖/无挑战
经济扫描 资源单调上升 → 通胀;Payback 某层 >2× 中位 → 沙漠
可解性扫描 任何生成结果无解 → 阻断级 bug
一致性扫描 显示值 vs 实际值不符 → 信任 bug

输出形式:一份可读的报告,标红项直接进 backlog。 目标:让"平衡问题"在被人发现之前被机器发现。

6. 系统侧 Bug 高发区(优先测这些)

高发区 典型 bug 测试方式
边界条件 数值为 0/负数/上限 参数化边界测试
状态叠加 多个增益同时生效顺序错误 组合矩阵测试
存档/读档 读档后状态不一致 存档往返测试(存→读→比对)
时间依赖 暂停/加速/切后台导致计时错乱 时间注入测试
随机 无种子、随机不可复现 种子复现测试
UI 与逻辑脱钩 显示的值 ≠ 实际的值 一致性断言
生成 不可解、卡死 批量生成 + 求解器验证
经济 溢出、负数、无限循环套利 长时模拟(100h)
本地化 字符串溢出、占位符丢失 最长语言膨胀测试
并发/网络(若适用) 状态不同步 回放测试

存档往返测试是最容易被忽略、后果最严重的:玩家丢档 = 差评 + 退款。 必须自动化:存 → 读 → 全状态比对。

7. QA 分层与验收

层 谁做 频率 关注
自动化 机器 每次提交/构建 逻辑、数值、回归、可解性
开发自测 开发者 每日 功能是否可用、边界
内部试玩 全团队 每周 手感、节奏、明显问题
外部试玩 招募玩家 每迭代 体验、理解、乐趣(见 production/16)
出货验收 全员 出货前 checklists/01 G4

关键分工:

  • 自动化回答"对不对"
  • 人工回答"好不好"
  • 不要用人工去查机器能查的东西(浪费),也不要用机器去判断乐趣(做不到)

8. 反模式

症状 修法
所有验证靠人肉试玩 建 harness,把可自动化的自动化
随机无种子 一切随机源自种子
逻辑与动画绑定 逻辑层可独立运行(无头模式)
数值散落在代码里 参数外置
无回归基准 建黄金数据 + 版本标签
改了数值不知道影响了什么 每次构建跑全量扫描
存档往返未测 自动化:存→读→比对
只在"功能完成"时测 每次提交跑 L1
用人工查数值边界 参数化边界测试
黄金数据被绕过(失败就更新) 差异 >15% 必须解释原因
无 headless 模式 优先实现,是 harness 的前提
生成结果不验证可解性 求解器自动验证,阻断级

9. 交付物

  1. 可测试性检查表(确定性/参数外置/可观测/可注入/可跳过)
  2. 模拟 harness 规格(无头模式 + 三种机器人策略 + 数据导出)
  3. 黄金数据基准文件(带版本标签)
  4. 自动化扫描报告模板(五类扫描 + 红项)
  5. 边界条件测试清单(按系统)

10. 参考

  • systems/08-numbers-and-formulas.md(蒙特卡洛与机器人跑测)
  • systems/09-balance-workflow.md(三张诊断表)
  • production/16-prototyping-and-playtest.md(人工试玩的正确用法)