关于 soak-test
soak-test 是为游戏项目生成长时间游玩测试方案和分析文档的技能。它帮助团队观察内存、稳定性、性能变化和玩法疲劳;实际游玩由人工完成。
主要功能
- 01生成定时观察检查点
- 02支持内存、稳定性和平衡性关注项
- 03提供引擎特定的监测指引
- 04记录会话预算和观察结果
- 05生成 QA 测试方案文档
适用场景
- 01跟踪长时间游玩中的内存增长
- 02检查崩溃或性能随时间的变化
- 03评估内容耗尽和玩法疲劳
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ donchitos/ claude-code-game-studios --skill soak-test安装后在 Claude Code 中输入/soak-test确认已加载。
详细介绍
!bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow
自动化模式:解析 modes.automation(project.local.yaml →
project.yaml → 默认值 collaborative)。每次调用 AskUserQuestion 和
每次文件写入都遵循 .claude/docs/automation-modes.md
(collaborative 始终提问 · guided 仅重大事项提问 · autonomous 记录并继续;
automation_always_ask 类别始终提问)。
长时间运行测试
长时间运行测试(也称耐久测试)是一种带有特定观察目标的长时间游戏体验。与冒烟检查(覆盖广泛的关键路径,约 10 分钟)或单项功能试玩(约 30 分钟)不同,长时间运行测试会持续 30 分钟到数小时,以发现:
- 内存泄漏 — 只有在场景切换后才会显现的堆内存逐渐增长
- 性能漂移 — 随时间推移而恶化的帧耗时
- 状态累积错误 — 只有在某个机制重复 N 次后才会出现的问题(库存已满、分数溢出、AI 状态损坏)
- 乐趣疲劳 — 初次体验时感觉不错,但长时间游玩后逐渐变得重复的机制
- 内容耗尽 — 玩家失去新鲜感、无内容可玩的时刻
此技能会生成观察方案和分析工具 — 实际游玩由人类完成。
输出: production/qa/soak-test-[date]-[duration].md
运行时机:
- 润色阶段 — 在
/gate-check release之前 - 修复内存或稳定性问题后(回归长时间运行测试)
- 尚未正式跟踪长时间游玩情况时
1. 解析参数
时长(默认值:1h):
30m— 短时测试;适合测试单个机制或场景1h— 标准测试;覆盖大多数常见泄漏类别2h— 延长测试;建议用于首次完整的润色阶段测试4h— 深度测试;面向单次游戏时长较长的游戏(RPG、模拟游戏)
重点(默认值:all):
memory— 重点关注堆大小、对象数量和泄漏模式stability— 重点关注崩溃、冻结和卡死检测balance— 重点关注乐趣疲劳、内容耗尽和难度感知all— 包含以上所有内容
2. 加载上下文
读取:
project.yaml—engine.name(用于获取特定引擎的内存监控 指引)和performance.*预算(内存上限、目标 FPS);对于缺失或为空的键 (包括project.yaml中没有performance或engine区块的情况),回退到.claude/docs/technical-preferences.mddesign/gdd/game-concept.md— 预期单次游戏时长(用于与测试时长对比)、核心循环说明 (若rigor: minimal,则改读替代它的一页简介design/game-brief.md, 获取核心循环;仅当其 “Who it's for” 行注明时,才获取单次游戏时长)。按章节读取: 使用 Grep 工具(模式^#,内容模式)查找所需标题,再使用带有 offset 和 limit 的 Read 工具读取对应范围。production/qa/playtests/中最近的文件 — 之前的试玩结果 (避免重复记录已知问题)- 最近的
production/qa/qa-plan-*.md文件 — 当前迭代的测试覆盖范围 (了解哪些内容已正式测试,以及长时间运行测试会覆盖哪些内容)
记录任何性能预算目标(project.yaml 中的 performance.*,否则查阅 .claude/docs/technical-preferences.md):
- 内存上限:[N MB,或“未设置”]
- 目标 FPS:[N,或“未设置”]
- 帧预算:[N ms,或“未设置”]
3. 定义观察检查点
根据时长生成定时检查点:
30m 测试:T+0、T+10、T+20、T+30 1h 测试:T+0、T+15、T+30、T+45、T+60 2h 测试:T+0、T+20、T+40、T+60、T+80、T+100、T+120 4h 测试:T+0、T+30、T+60、T+90、T+120、T+180、T+240
在每个检查点,观察者都要记录第 4 阶段中定义的观察项目。
4. 生成长时间运行测试方案
内存 / 稳定性观察项(如果 focus = memory 或 all)
引擎专属的监控指南。
记录工具显示的单位;绝不换算,也绝不自行假定单位。 浸泡测试关注的是增长,因此下方的每个阈值都是相对于本次会话自身 T+0 基线的比率或增量——不依赖单位,无论编辑器如何显示数值都始终适用。在 T+0 按原样记录单位,并在本次运行的其余时间里保持一致。
无法从源文件中核实——下方的工具、面板和计数器名称不在
docs/engine-reference/的覆盖范围内:Godot 的 Debugger → Monitors 及其内存计数器、Unity 的 Memory Profiler 及其字段、Unreal 的stat memory。请在协议中标明这一点:它们只是指引测试人员在 T+0 时于自己的编辑器中确认,并非已核实的路径。如果找不到内存工具,则表示未进行任何测量,适用 Verdict 部分中的 NOT ASSESSED。
Godot 4:
- 打开 Debugger → Monitors 标签页;在各个检查点跟踪
Memory → Static Memory和Object Count → Objects - 记录:Static Memory(按显示的单位)、Object Count、Orphan Nodes 数量
- 警告阈值:前 15 分钟后,内存相较 T+0 增长 > 20%(加载时出现一定增长是正常的;持续增长则表明存在泄漏)
- Orphan Nodes 是唯一值得关注的绝对数值:场景卸载后,它应恢复到 T+0 时的值。比率会掩盖这一点;无论单位如何,若非零基线持续上升,就表明存在泄漏
Unity:
- 打开 Memory Profiler(Window → Analysis → Memory Profiler)
- 在各个检查点记录:Total Reserved Memory、GC Allocated、Object Count(按显示的单位)
- 警告阈值:GC Allocated 在连续 3 个或更多检查点中持续增长——这是单调性检查,刻意不依赖单位
Unreal Engine:
- 在每个检查点使用
stat memory控制台命令 - 记录:Physical Memory Used、Physical Memory Available(按显示的单位)
- 警告阈值:整个浸泡测试期间 Physical Memory Used 增长 > 20%,以本次运行的 T+0 为基准。像“> 50MB”这样的绝对阈值会悄然假定单位和项目规模——对某个游戏来说,50MB 只是舍入误差;对另一个来说,却是灾难
稳定性观察项(如果 focus = stability 或 all)
在每个检查点记录:
- 自上一个检查点以来,没有发生崩溃、卡顿或冻结
- 帧率仍在目标预算内([target FPS] fps)
- 音频仍正常播放(没有不同步或无声)
- 所有 HUD 元素仍正常渲染
- 输入响应符合预期(没有输入丢失或延迟峰值)
平衡性 / 疲劳度观察项(如果 focus = balance 或 all)
在每个检查点收集主观观察:
- 核心机制仍然带来成就感(Y/N)
- 感知到的难度:[太简单 / 适中 / 太难]
- 自上一个检查点以来,是否出现过“似曾相识”的时刻?(内容新鲜感耗尽)
- 自上一个检查点以来,是否出现过受挫的时刻?记录原因。
- 自上一个检查点以来,是否出现过投入感最强的时刻?记录原因。
5. 生成协议文档
# Soak Test Protocol
> **Date**: [date]
> **Duration**: [duration]
> **Focus**: [memory | stability | balance | all]
> **Engine**: [engine]
> **Generated by**: /soak-test
---
## Pre-Session Setup
Before starting the soak:
- [ ] Game is running from a **fresh launch** (not resumed from a prior session)
- [ ] All background applications closed (minimise OS memory interference)
- [ ] Performance monitoring tool open and recording:
- **Godot**: Debugger → Monitors tab → Memory section visible
- **Unity**: Memory Profiler window open
- **Unreal**: `stat memory` ready in console
- Tool actually used, as named in this editor: [record it — the names above
are NOT SOURCEABLE from `docs/engine-reference/`; none found → NOT ASSESSED]
- [ ] Soak target confirmed: [session design intent from game concept]
- [ ] Prior known issues to watch for: [from most recent playtest / qa-plan]
---
## Baseline (T+0) — Record Before Playing
| Metric | Baseline Value |
|--------|---------------|
| Memory / Heap | [record before first frame of gameplay] |
| Object Count | [record] |
| FPS (first 30 seconds) | [record] |
| [Engine-specific metric] | [record] |
---
## Checkpoint Log
### T+[N] minutes
**Memory / Stability** *(if applicable)*:
| Metric | Value | Δ from Baseline | Alert? |
|--------|-------|-----------------|--------|
| Memory / Heap | | | |
| Object Count | | | |
| FPS | | | |
| Crashes / Hangs | | | |
**Stability checks**:
- [ ] No crash or hang since last checkpoint
- [ ] Frame rate within budget ([N] fps target)
- [ ] Audio correct
- [ ] HUD rendering correctly
- [ ] Input responding correctly
**Balance / Fatigue** *(if applicable)*:
- Core mechanic still rewarding: Y / N
- Difficulty perception: too easy / appropriate / too hard
- Notable moments: [note any peak engagement or frustration]
- Content exhaustion signs: Y / N — [describe]
**Free observations**:
*(Note anything unexpected observed since the last checkpoint)*
---
[Repeat Checkpoint Log section for each timed checkpoint]
---
## Post-Session Analysis
### Memory Trend
| Checkpoint | Memory | Δ/hr extrapolated |
|------------|--------|-------------------|
| T+0 | | |
| [T+N] | | |
**Leak detected?** Y / N
**Estimated time to OOM at current rate**: [N hours / not applicable]
### Stability Summary
Total crashes: [N]
Total hangs: [N]
Worst FPS observed: [N] fps at [checkpoint]
Performance degradation: stable / mild / severe
### Balance / Fatigue Summary
Fun curve: [engaged throughout / fatigue onset at T+N / repetitive from start]
Content exhaustion point: [never / at T+N / early]
Difficulty arc: [appropriate / too easy throughout / difficulty spike at T+N]
### Issues Found
| ID | Severity | Checkpoint | Description |
|----|----------|------------|-------------|
| SOAK-001 | S[1-4] | T+[N] | [description] |
---
## Verdict: PASS / PASS WITH CONCERNS / NOT ASSESSED / FAIL
**PASS**: No leaks detected, stability maintained, fun factor consistent
**PASS WITH CONCERNS**: Minor drift or fatigue noted; addressable in Polish
**NOT ASSESSED**: The soak did not run to a length that could show what it looks
for — say how far it got and which checkpoints were never reached
**FAIL**: Memory leak confirmed, stability breach, or severe fun fatigue
> **A short soak cannot return PASS.** Everything this protocol exists to detect
> — slow leaks, fatigue, late-appearing edge cases — is by definition invisible
> early, so a session that ended before the checkpoints it was built around has
> not shown stability; it has shown nothing yet. Record `NOT ASSESSED — reached
> T+[N] of [duration]; checkpoints [list] not reached`. Ranks **above both pass
> values** and **below FAIL**: a crash observed at T+20 is a real finding no
> matter how short the run, and must not be demoted behind the run's length.
> The same applies when the build crashed for reasons unrelated to the soak, when
> no memory instrumentation was available (nothing was measured, so "no leaks
> detected" means "no leaks could have been detected"), or when the protocol was
> written but never executed — a protocol document is not a result.
---
## Sign-Off
- **Tester**: [name] — [date]
- **QA Lead review**: [name] — [date]
6. 写入输出
先在对话中提供协议摘要,然后询问:
“我可以将此浸泡测试协议写入
production/qa/soak-test-[date]-[duration].md 吗?”
仅在获得批准后写入。
写入后:
“协议已写入。运行浸泡测试:
- 打开文件并按照会话前设置清单操作
- 游戏过程中记录每个检查点
- 完成后填写会话后分析部分
- 将‘发现的问题’中的 Bug 提交到
production/qa/bugs/ - 会话结束后运行
/bug-triage sprint,以整合任何 S1/S2 问题(在workflow: minimal下,该流程没有 sprint:运行/bug-triage full)
如果判定结果为 FAIL,请修复问题后再次运行 /smoke-check。”
协作协议
- 此技能会生成协议,由人类执行——切勿尝试自动运行长时间测试。观察过程需要人工监督者。
- 测试时长应与游戏的会话设计相匹配——5 分钟的游戏无需进行 4 小时的长时间测试;城市建造类游戏则可能需要。请自行判断,不确定时先询问。
- 首次长时间测试应采用
all焦点——缩小焦点范围(仅关注内存)适用于特定修复后的回归测试,而非首次测试 - 写入前先询问——创建协议文件前务必先确认