Files
gplan-2/game/tests/README.md
T

78 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Test Infrastructure — Dungeon Sweeper
**Engine**: Godot 4.7.2-stable(GDScript 单语言)
**Test Framework**: 双载体(ADR-0004)——`--headless --script` 逻辑冒烟 + headless 场景探针;gdUnit4 **deferred**(D2 OQ1 关闭形态,正式 CI 期再议)
**CI**: `.github/workflows/tests.yml`(首次 push 到 GitHub 后自动生效;仓库已初始化 git、尚未配置远端)
**Setup date**: 2026-09-12(2026-09-27 `7f24b640` 三层收敛:根 tests/ 并入 `game/tests/`、docs 并入 `design/dev/`、production 解散)
**参考实现**: `game/smoke/`(冒烟断言 + 场景探针族——正式工程的活样板;断言计数双口径见下节)
## Directory Layout
```
tests/
unit/ # 隔离单元测试(公式/状态机/纯逻辑)——extends SceneTree + quit(code)
smoke/ # critical-paths.md——人工 gate 清单(/smoke-check 读取)
evidence/ # 截图与人工签核记录
run_all.gd # CI 冒烟统一入口(套件 manifest 协议,D2 AC-2b)
static_scan.sh # ADR-0004 静态扫描域 S1–S8 可执行子集
```
> integration/ 目录已删空壳(迭代 19 卡① T4/Q8 2026-10-08——彼时仅有章程 README 无实体)。章程句保留在此:将来跨系统测试(Core-Core 集成、回放确定性〔同种子步骤流逐行相同——B1 AC-33 形态〕、存档/RNG 快照往返、A1×A2 双包含端到端)落地时随批建 `tests/integration/` 迁入;各 GDD 登记的 deferral 集成用例以对侧登记为生效条件。
## 断言计数双口径(2026-10-08 迭代 19 卡① T4 订正)
历史 README 写死「752+ 断言/十五套件」必然漂移,改为两种口径并注明语义:
- **运行时口径**:`python tools/run_smoke.py` 打印的通过项数(迭代 19 卡①分支基点实测 **840 项 0 失败**,2026-10-08;master 合并卡②④后为 846——随断言面增减浮动,以当次跑测打印为准)——循环内断言按执行次数计。
- **静态口径**:`game/smoke/` 源码 `check(` 调用点计数(2026-10-08 本分支实测 **764 处**)——按源码位置计,一处在循环内即多次执行,故两口径数值不同且各自浮动,禁互相换算或写死。
## Running Tests
```bash
# 逻辑冒烟(双载体之一)——Windows 须用 console 版 exe 取 stdout;工作目录 = game/(含 project.godot 那一层)
godot --headless --script tests/run_all.gd # 统一入口(CI 调用点)
godot --headless --script tests/unit/example_test.gd
# 场景探针(双载体之二)——以探针场景为运行目标,走完整项目引导(autoload 在位)
godot --headless --path . res://smoke/<probe>.tscn
# CI 旁必须配外部 wall-clock 超时(ADR-0004:引擎无死锁探测)
timeout 120s godot --headless --script tests/run_all.gd
```
> 单元/契约套件状态(单元测试与契约层批 2026-09-28 立基,后随迭代 7/8 增补):`_suites()` manifest 已登记实跑 **18 套件**(第 18 套 = 迭代 19 卡④提灯载体批新增 `unit/core/fog_lantern_wiring_test` 提灯装配链〔行加载/schema/只读出口双态/enc 注入面〕——本分支基点早于卡④合并时实测 17 套全绿,合并后 18)——data_config(ConfigDB 加载/进度坐标 ceil 解析/fatal 退出码/统一随机流)、core(秘宝结构冻结/断点续玩/提灯装配链)、battle_settlement(DamageMath 纯函数/DamageController 伤害单据五配方)、contracts(系统间接口契约断言)、presentation(节奏队列/奖励浮层/字体资产/地形瓦片集);致命类独立进程 `expect=1`。期望值一律由表读值推导(零玩法数值字面量)、随机只经 RngService 统一流。
**协议要点**(D2 冒烟协议 + ADR-0004):
- 冒烟脚本 `extends SceneTree` 以获得 `quit(code)`;成功 `quit(0)`、失败 `quit(1)`
- `--script` 模式**不加载 autoload 且不注册全局标识符**(裸引用 `ConfigDB` = parse error)——ConfigDB/RngService 由脚本显式实例化,core 一律构造注入
- 致命类用例独立进程,runner manifest 登记"调用 → 期望退出码"
- 每用例先 `reset_diagnostics()`(诊断收集器协议)
- 期望值由表读值推导,不写死玩法数值
## Test Naming
- **Files**: `[system]_[feature]_test.gd`(领域命名,禁 ID 前缀——design/dev/code-conventions.md)
- **Functions**: `test_[scenario]_[expected]`
- **Example**: `reward_roll_test.gd` → `test_power_interval_rolls_within_bounds()`
## Story Type → Test Evidence
| Story Type | Required Evidence | Location |
|---|---|---|
| Logic | Automated unit test — must pass | `tests/unit/[system]/` |
| Integration | Integration test OR playtest doc | 落地时随批建 `tests/integration/[system]/`(目录已删空壳,章程见上) |
| Visual/Feel | Screenshot + lead sign-off | `tests/evidence/` |
| UI | Manual walkthrough OR interaction test(场景探针为首选) | `tests/evidence/` |
| Config/Data | Smoke check pass | `design/qa/` |
## Static Scan(提交前双跑:本地 + CI)
`tests/static_scan.sh` 实现 ADR-0004 扫描域 S1–S8 的可执行子集;规则全集与动机见
`design/dev/architecture/adr-0004-test-carrier-and-ci.md`。新违规案例必须**先补扫描规则再修码**。
## CI
Tests run automatically on every push to `main` and on every pull request.
A failed test suite blocks merging. **gdUnit4 安装说明(deferred,届时启用)**:
AssetLib → GdUnit4 → Install → Project Settings → Plugins 勾选 → 重启编辑器 → 确认 `res://addons/gdunit4/`。