mcpField
S
soak-test

soak-test

github.com/donchitos测试与质量28.5k450 次安装1 周前更新
代码仓库

关于 soak-test

soak-test 是为游戏项目生成长时间游玩测试方案和分析文档的技能。它帮助团队观察内存、稳定性、性能变化和玩法疲劳;实际游玩由人工完成。

主要功能

  1. 01生成定时观察检查点
  2. 02支持内存、稳定性和平衡性关注项
  3. 03提供引擎特定的监测指引
  4. 04记录会话预算和观察结果
  5. 05生成 QA 测试方案文档

适用场景

  1. 01跟踪长时间游玩中的内存增长
  2. 02检查崩溃或性能随时间的变化
  3. 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.md
  • design/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 吗?”

仅在获得批准后写入。

写入后:

“协议已写入。运行浸泡测试:

  1. 打开文件并按照会话前设置清单操作
  2. 游戏过程中记录每个检查点
  3. 完成后填写会话后分析部分
  4. 将‘发现的问题’中的 Bug 提交到 production/qa/bugs/
  5. 会话结束后运行 /bug-triage sprint,以整合任何 S1/S2 问题(在 workflow: minimal 下,该流程没有 sprint:运行 /bug-triage full)

如果判定结果为 FAIL,请修复问题后再次运行 /smoke-check。”


协作协议

  • 此技能会生成协议,由人类执行——切勿尝试自动运行长时间测试。观察过程需要人工监督者。
  • 测试时长应与游戏的会话设计相匹配——5 分钟的游戏无需进行 4 小时的长时间测试;城市建造类游戏则可能需要。请自行判断,不确定时先询问。
  • 首次长时间测试应采用 all 焦点——缩小焦点范围(仅关注内存)适用于特定修复后的回归测试,而非首次测试
  • 写入前先询问——创建协议文件前务必先确认

评论

支持 Markdown