# 59 · QA 测试框架(QA Testing Framework) > **命名空间** `BaseGames.QA` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **依赖** Unity Test Framework · `BaseGames.Reliability` · `BaseGames.Analytics` > **关联** 49_AntiSoftlockSystem · 56_CrashRecoverySystem · 46_PlatformIntegration · 29_DifficultyModesGuide --- ## 目录 1. [QA 策略总览](#1-qa-策略总览) 2. [自动化测试分层架构](#2-自动化测试分层架构) 3. [关键系统回归清单](#3-关键系统回归清单) 4. [平台认证矩阵(TCR/TRC)](#4-平台认证矩阵tcrtrc) 5. [Softlock 测试方法论](#5-softlock-测试方法论) 6. [本地化 QA 流程](#6-本地化-qa-流程) 7. [性能基准 SOP](#7-性能基准-sop) 8. [Bug 等级分类与阻塞标准](#8-bug-等级分类与阻塞标准) 9. [PlayTest 流程规范](#9-playtest-流程规范) 10. [CI/CD 质量门禁](#10-cicd-质量门禁) --- ## 1. QA 策略总览 ``` QA 测试金字塔 ┌─────────────┐ │ 手动 QA │ ← PlayTest / 平台认证 / 本地化审校 │ (少量,慢) │ ├─────────────┤ │ 集成测试 │ ← 跨系统流程(存档↔进度、对话↔任务) │ │ ├─────────────┤ │ 单元测试 │ ← 纯逻辑(伤害计算、存档序列化、物理层) │ (大量,快) │ └─────────────┘ ``` **测试目标**: - 发行日不存在 P0/P1 Bug - 平台认证一次通过(不因可预期的问题而拒审) - 关键游戏数据(存档、能力解锁)不因边界条件损坏 **QA 工具链**: - Unity Test Framework(EditMode + PlayMode) - Custom QA CI Runner(GitHub Actions / 本地 MSBuild) - GameCI Docker(Unity 无头构建) - 手动 Bug 追踪(GitHub Issues 或 Notion) --- ## 2. 自动化测试分层架构 ### 2.1 EditMode 测试(纯逻辑,不需要场景) 存放路径:`Assets/Tests/EditMode/` | 测试文件 | 覆盖内容 | |---------|---------| | `SaveDataSerializationTests.cs` | 存档 JSON 序列化/反序列化往返,版本迁移 | | `DamageCalculationTests.cs` | 伤害公式、暴击、减伤计算 | | `PhysicsLayerTests.cs` | Layer 注册正确、Collision Matrix 符合 57_PhysicsLayerMatrix | | `EconomyTests.cs` | Geo 计算、稀有掉落保底逻辑(EconomyConfigSO)| | `CompletionTrackerTests.cs` | 完成度积分计算,各分类加分逻辑 | | `WorldStateRegistryTests.cs` | SetFlag/HasFlag/LoadFromSave 往返一致性 | | `AbilityGateTests.cs` | AbilityGate 阻挡/通过逻辑 | | `SpeedrunTimerTests.cs` | IGT 在各种暂停状态下的计时精度 | ### 2.2 PlayMode 测试(需要场景上下文) 存放路径:`Assets/Tests/PlayMode/` | 测试文件 | 覆盖内容 | |---------|---------| | `PlayerMovementTests.cs` | 跳跃、冲刺、抓墙物理行为 | | `CombatFlowTests.cs` | 攻击 → HitBox → HurtBox → 伤害 → 击退完整流程 | | `SaveLoadCycleTests.cs` | 存档 → 读档 → 状态一致(跨场景)| | `DialogueTriggerTests.cs` | NPC 交互 → 对话触发 → 完成 → 状态变更 | | `SoftlockDetectorTests.cs` | SoftlockDetector 计时器触发行为 | | `RoomTransitionTests.cs` | 场景切换、传送、存档点等场景跳转流程 | ### 2.3 测试运行命令 ```bash # 运行所有 EditMode 测试(无需 Unity 编辑器 GUI) unity -runTests -testPlatform EditMode -projectPath . -testResults ./TestResults/EditMode.xml # 运行所有 PlayMode 测试 unity -runTests -testPlatform PlayMode -projectPath . -testResults ./TestResults/PlayMode.xml ``` --- ## 3. 关键系统回归清单 每次发布前**必须**手动验证的核心流程(自动化未覆盖的场景): ### 3.1 存档系统 - [ ] 存档 → 强制退出 → 重启 → 进度完整 - [ ] 在 Boss 房间内强制退出 → 重启 → 在 Boss 房间外重生(不是在 Boss 房间里) - [ ] 3 个存档槽独立,不相互干扰 - [ ] 硬件时钟倒退后,存档时间戳不异常 - [ ] 磁盘满时,错误 UI 正常显示(手动制造磁盘满条件) ### 3.2 进度与能力 - [ ] 获得双跳后,双跳立即可用(不需要重启) - [ ] 冲刺能力解锁后,冲刺 AbilityGate 正确开启 - [ ] NG+ 开始后,继承列表中的能力/符文完整 - [ ] NG+ 不继承 Boss 状态(Boss 重置为未击败) ### 3.3 地图与世界 - [ ] 所有房间首次进入后,地图正确标记 - [ ] 地图上的 NPC 图标随 NPC 迁移而更新 - [ ] 商店库存随进度解锁 - [ ] 所有房间都能从入口正常进入/退出(无穿模) ### 3.4 战斗 - [ ] 攻击 HitBox 在各方向正确(上攻/下攻/左右攻方向一致) - [ ] 弹反判定窗口与动画帧同步 - [ ] Boss 各阶段转场正确(不跳相) - [ ] 死亡 → Geo 掉落 → 拾取 Geo 恢复 - [ ] 永久死亡(Geo 无法恢复)的边界条件(掉入深渊底部) ### 3.5 对话与叙事 - [ ] 关键 NPC 的对话版本随世界状态标志正确切换 - [ ] 长对话跳过后,剧情标志仍然正确设置 - [ ] 侧任务完成条件满足后,任务 UI 正确完成 --- ## 4. 平台认证矩阵(TCR/TRC) > 每个平台的具体认证要求参见 46_PlatformIntegration.md §4。本表列出常见拒审原因及对应测试项。 | 平台 | 常见拒审原因 | 测试项 | |------|-----------|-------| | **Steam** | 游戏崩溃 / 卡死 / 无响应 | 4小时稳定性测试(各区域循环游玩)| | | 成就不触发 | 每个成就手动验证触发条件 | | | 截图库无截图 / 描述不准确 | 按 Steam 商店指南核对资产 | | **Nintendo Switch** | 休眠后无法恢复(挂起/恢复) | 在各游戏状态下触发 Switch 休眠,恢复后验证 | | | 控制器断开后崩溃 | 运行时拔出 Joy-Con,验证提示 UI | | | 未使用 Switch 按钮图标 | 检查所有操作提示图标(A/B/X/Y 不用 XBox 图标)| | | 本地多人存档不隔离 | 多用户账号分别进行存档验证 | | | Home Menu 警告文本缺失 | 检查所有 Modal 有无必要的 Home Menu 提示 | | **PlayStation** | 数据管理要求(自动存档) | TRC T-09X 系列:自动存档符合 TCR | | | 奖杯不解锁 / 解锁过多重复 | 每个奖杯手动验证,确认不重复触发 | | | 营销资产规格不符 | 按 PlayStation 素材规格核对 | ### Switch 强制测试项 ``` 测试: 挂起/恢复 (Suspend/Resume) 环境: 在以下每种状态下触发 Switch 休眠键 - 主菜单 - 正常游玩(普通房间) - Boss 战中 - 过场动画播放中 - 存档中(SaveIndicator 可见时) - 加载中(黑屏过渡) 预期结果: 恢复后游戏完整可用,无崩溃,无数据丢失 ``` --- ## 5. Softlock 测试方法论 > 配合 49_AntiSoftlockSystem.md §6 的 `EscapeGuaranteeValidator` 工具使用。 ### 5.1 自动化检查(EditorWindow BFS) 1. 打开 `Tools → Zeling → Escape Guarantee Validator` 2. 点击"Run All Rooms",工具遍历所有房间的 `RoomEscapeInfoSO` 3. 检查是否每个房间都有对应所有能力状态的逃生路线 ### 5.2 手动 Softlock 测试清单 | 测试场景 | 操作步骤 | 预期行为 | |---------|---------|---------| | 无能力状态进入任何房间 | 使用 Debug 模式删除全部能力,进入目标房间 | SoftlockDetector 45s 后触发,传送选项出现 | | 被敌人推入凹陷地形 | 找到地图中所有凹形地形,测试是否可逃出 | 能跳出,或跌落重生 | | Boss 房间门关闭后能力丢失 | 进入 Boss 房间 → 通过 Debug 移除 Dash → Boss 死亡门未开 | SoftlockDetector 触发,或 Boss 房间门有保底开门逻辑 | | 液体区域无游泳能力 | 进入液体区域,移除游泳能力 | 玩家在液体中逐渐失血,死亡后正常重生(不卡死)| | AbilityGate 入口无出口 | 进入 AbilityGate 保护的区域,然后条件不满足 | 区域内必须有出口或逃生路线(EscapeGuaranteeValidator 保证)| --- ## 6. 本地化 QA 流程 ### 6.1 支持语言列表 | 语言 | 代码 | 审核负责人 | |------|------|---------| | 简体中文(主语言)| zh-CN | 内部团队 | | 繁体中文 | zh-TW | 外包审校 | | 英文 | en | 外包翻译 + 内部审核 | | 日文 | ja | 外包翻译(必须含母语审校)| | 韩文 | ko | 外包翻译(建议)| ### 6.2 本地化 QA 检查项 - [ ] **文本溢出**:所有 UI 文本在最长翻译(通常是德文/日文)下不溢出容器 - [ ] **字体覆盖**:所有语言的特殊字符正确显示(日文假名、韩文字符、中文繁体异体字) - [ ] **语境正确性**:道具名称/NPC 名称在句子中语法正确(特别是日语助词) - [ ] **图像内文字**:所有包含硬编码文字的图像都有对应语言版本 - [ ] **音频字幕同步**:过场动画字幕与原声音频时间轴对齐(±0.5s 内) - [ ] **数字格式**:货币、日期格式符合各地区习惯(如日文不用逗号分隔千位数) ### 6.3 本地化自动检查工具 ```csharp // 在 CI 中运行 LocalizationAuditTool,自动检测: // 1. 所有本地化 Key 都有对应翻译(无缺失 Key) // 2. 无翻译超过容器字数限制(基于 Font Asset + TextMeshPro 计算) // 3. 所有音频 Key 对应的音频文件存在 LocalizationAuditTool.RunAudit(outputPath: "./TestResults/LocalizationAudit.html"); ``` --- ## 7. 性能基准 SOP ### 7.1 目标平台性能指标 | 平台 | 目标帧率 | 允许最低帧率 | 内存上限 | |------|---------|-----------|---------| | PC(中端,GTX 1060)| 60 FPS | 45 FPS(极端粒子特效)| 2 GB RAM | | PC(低端,集成显卡)| 30 FPS(低质量预设)| 25 FPS | 1.5 GB RAM | | Nintendo Switch(TV 模式)| 60 FPS | 50 FPS | 3.5 GB RAM | | Nintendo Switch(手持模式)| 60 FPS | 45 FPS | 3.5 GB RAM | ### 7.2 性能测试标准场景 每次大版本发布前在以下场景运行 5 分钟帧率采样: | 场景 | 测试内容 | |------|---------| | `Scene_Forest_Main`(大地图)| 正常游玩,含大量背景层植被 | | `Scene_Cave_BossArena`(Boss 战)| Abyss Boss 第3阶段(最多粒子特效)| | `Scene_Core_Final`(最终区域)| 最多光照/后处理 | | `Scene_StressTest_500Enemies`(压测)| 人工压测场景,500个激活敌人 | ### 7.3 性能基准工具 ```csharp // 在场景中放置 PerformanceBenchmarkRunner 组件 // 运行后输出 CSV:帧率、CPU ms、GPU ms、内存、DrawCall 等 [RequireComponent(typeof(Camera))] public class PerformanceBenchmarkRunner : MonoBehaviour { [SerializeField] float testDurationSeconds = 300f; [SerializeField] string outputPath = "TestResults/Performance/"; // 每帧记录 FrameTimingManager 数据,结束后输出 CSV } ``` ### 7.4 内存泄漏检测 SOP 1. 打开 Unity Memory Profiler(包名:`com.unity.memoryprofiler`) 2. 在 `Scene_Forest_Main` 游玩 10 分钟,每隔 2 分钟截取一次内存快照 3. 比较前后快照,检查 `MonoBehaviour` / `Texture2D` / `AudioClip` 是否持续增长 4. 重点检查:切换场景后旧场景的 Addressable 资源是否正确卸载 --- ## 8. Bug 等级分类与阻塞标准 | 等级 | 定义 | 示例 | 发布阻塞 | |------|------|------|---------| | **P0(致命)** | 导致游戏无法进行,数据丢失,或认证不通过 | 存档损坏、游戏崩溃、平台认证必需功能缺失 | 🔴 必须修复后方可发布 | | **P1(严重)** | 游戏流程卡死,主线任务无法完成 | Softlock、Boss 无敌、主线对话不触发 | 🔴 必须修复后方可发布 | | **P2(主要)** | 功能异常但有规避方法,或影响较大的视觉/音频 Bug | 支线任务 Bug、成就不触发、音频缺失 | 🟡 目标修复,首发前尽力解决 | | **P3(次要)** | 小视觉 Bug,不影响游戏性 | 个别图层 z-order 错误、UI 文字截断 | 🟢 可首发后热更新 | | **P4(优化)** | 性能问题或用户体验改善建议 | 帧率偶尔下降、操作手感微调 | 🟢 可后续版本跟进 | --- ## 9. PlayTest 流程规范 ### 9.1 内部 PlayTest | 阶段 | 时机 | 目标 | 参与者 | |------|------|------|--------| | **Alpha PlayTest** | 核心系统完成后 | 核心游戏循环验证,P0/P1 Bug 猎杀 | 开发团队 | | **Beta PlayTest** | 内容完整后 | 完整流程通关,难度曲线,本地化初检 | 团队 + 10~20 名外部测试者 | | **Pre-cert PlayTest** | 提交平台认证前 2 周 | 模拟平台认证检查,平台合规 | 专注平台认证的 QA | | **Gold Candidate** | 发行前 1 周 | 最终回归,P0/P1 清零确认 | 全团队 | ### 9.2 PlayTest 问卷(标准版) 外部 PlayTest 结束后必须填写: 1. 整体评分(1~10) 2. 操作手感评分(1~10) 3. 难度评分(太简单 / 刚好 / 太难) 4. 是否遇到 Bug?(是/否,详细描述) 5. 是否遇到不明白如何继续的情况?(描述卡关位置) 6. 最喜欢的部分是什么? 7. 最不喜欢的部分是什么? 8. 游玩时长 --- ## 10. CI/CD 质量门禁 所有 PR 合并前必须通过以下自动化检查(GitHub Actions): ```yaml # .github/workflows/qa.yml(示例结构) quality_gates: - name: Unity Build (PC) command: unity -buildTarget StandaloneWindows64 -batchmode -quit fail_on: build_error - name: EditMode Tests command: unity -runTests -testPlatform EditMode fail_on: any_test_failure - name: Localization Audit command: dotnet run --project Tools/LocalizationAudit fail_on: missing_keys | overflow_detected - name: Physics Layer Validation command: unity -runTests -testPlatform EditMode -testFilter PhysicsLayerTests fail_on: any_test_failure - name: Code Coverage (minimum 60%) command: unity -runTests -enableCodeCoverage fail_on: coverage_below_60_percent ``` **门禁规则**:任何门禁失败,PR 不可合并,必须修复后重新提交。 --- *本文档版本 1.0 · 2026-04 · 关联 49_AntiSoftlockSystem / 56_CrashRecoverySystem / 46_PlatformIntegration*