测试层合并批(用户裁 2026-11-07): 「集成测试」层级退役归并单元层——tests/integration/ 三套件(存档⇄RNG 往返/节点图确定性/跨系统流×落盘)实体迁移 tests/unit/ 同闸同协议, run_all manifest 65 套全量单元; 闸名「单元与集成测试」→「单元测试」(run_all_gates/基线键/coverage_receipts 同步); 选闸词 integration 族→save_rng/cross_system/node_map 文件名词; 测试层识别换三元组(职责×触发时间点×覆盖面积, 权威表=test-conventions §1.1 测试层三元组), 层级名降为代称; 术语表退役词对照+doc_term 收「集成测试/用例/层/侧/宿主/族」, 全仓旧字样清零(gdd/规约/README/套件头注/断言标签), 跨系统面性质归属由各套件头注承载; extract_checks 缺省遍历面收 unit/**; test-conventions §8.2 验收四层「集成」改「跨宿主」; architecture 测试层级表三级换代+65 实数; domain_route/AGENTS 字样同步。凭据: 三套件单跑 exit=0; --code 域闸验收通过(冒烟/单元全量/系统/场景探针/渲染闸/静态扫描/熵增闸全绿); --docs 域闸验收通过(文档域七闸零新增红)

This commit is contained in:
DKChan committed 2026-11-07 01:59:49 +08:00
1 parent 40a3ac1281
commit 9f80609518
28 files changed
+139 -127

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@
# --gates),闸件改动不再零触发,也不在远端重复烧引擎。
# 3. diff 空 → skip。
# 判定面说明:game/tests/** 与 game/sim/** 属 game/ 行为载体(.md 除外)→ full,
# 与 run_all_gates.sh 关联档口径一致(测量面批单元与集成测试照跑全套件)。
# 与 run_all_gates.sh 关联档口径一致(测量面批单元测试照跑全套件)。
set -u
base="${1:-}"
head="${2:-HEAD}"
+2 -2
View File
@@ -8,7 +8,7 @@ tools/coverage_report.html 经 <script src> 直载。
六层与日志源(层键=面板消费键,层名=呈现名):
smoke 冒烟测试 smoke_boot.log 摘要「N 项检查,M 项失败」
unit 单元与集成测试 unit.log 每套件「[run_all] PASS/FAIL res://…(exit=N)」
unit 单元测试 unit.log 每套件「[run_all] PASS/FAIL res://…(exit=N)」
system 系统测试 system_test.log 摘要「N 项检查,M 项失败」
probe 场景探针 probe.log 每探针段「======== 名(段)========」+该段 PASS/FAIL 行
render 渲染闸 render.log golden 清单与对比结果
@@ -123,7 +123,7 @@ def parse_static(log: str) -> dict:
LAYERS = [
("smoke", "冒烟测试", "smoke_boot.log", parse_summary_layer),
("unit", "单元与集成测试", "unit.log", parse_unit),
("unit", "单元测试", "unit.log", parse_unit),
("system", "系统测试", "system_test.log", parse_summary_layer),
("probe", "场景探针", "probe.log", parse_probe),
("render", "渲染闸", "render.log", parse_render),
+4 -1
View File
@@ -70,12 +70,15 @@ RETIRED_TERMS = [
("插旗|标旗", "2026-10-18", "封印(正式动作名,全库统一)", "术语刷新批——「旗」概念退役"),
("完美排雷", "2026-10-19", "完美封印(正式名见 design/gdd/术语表.md 退役词对照)", "迭代 32 卡①反哺批 2026-10-21 用户裁入表——代码注释面由 S11 承接,文档正文面由此条承接"),
# —— 测试术语与层级重构批(2026-10-22 用户裁):权威=design/gdd/术语表.md「退役词对照」——
# 标准四级测试层(冒烟/单元/集成/系统)+UI 探针与 golden;闸档用语随三条频率规则消亡。
# 标准测试层(冒烟/单元/系统)+UI 探针与 golden;闸档用语随三条频率规则消亡。
# 「重闸」用负向后行断言排除机制词「去重闸」(封印重判去重判别器,在役非退役)。
("系统级断言套件|冒烟全量", "2026-10-22", "系统测试", "测试术语重构批——标准四级层命名(裁决录=提案 §二——提案已退役,考古=git 历史——删除批 53075baa,删除前全稿见历史版本 b4da36a8)"),
("单元套件", "2026-10-22", "单元测试", "测试术语重构批——标准四级层命名"),
("启动探针|秒级冒烟探针|L0[–-]L3", "2026-10-22", "冒烟测试", "测试术语重构批——极小启动场景"),
(r"(?<!去)重闸|轻闸|三查", "2026-10-22", "(随频率规则消亡:检出工作区零测试;卡内只测自己改的东西;全量只有批末+合回两个时机)", "测试术语重构批——闸档用语退役;代码注释面由 S11 承接(S11 设「去重闸」同形异义豁免)"),
# —— 测试层合并批(2026-11-07 用户裁):跨系统真实路径闭环套件归单元层,三套件实体迁移 tests/unit/;
# 测试层识别三元组=职责×触发时间点×覆盖面积(test-conventions「测试层三元组」节),层级名只是代称。
("集成测试|集成用例|集成层|集成侧|集成宿主|集成族", "2026-11-07", "单元测试(跨系统真实路径闭环套件归单元层,性质归属由套件头注承载)", "测试层合并批——「集成」层级词退役,文档正文面由此条承接,代码注释面由 S11 承接"),
# —— 旧词残留清扫批(2026-10-26 用户裁):权威=design/gdd/术语表.md「退役词对照」——
# 魔法道具=秘宝旧中文规范名(2026-10-05 消歧更名);罕见=旧三档档位名,现行四级第三档=稀有
# (档名映射见 adventure_table.gd 头注)——散文形容词义的「罕见」人工判读,不算档位名残留。
+7 -8
View File
@@ -13,14 +13,14 @@ r"""extract_checks.py — 断言静态提取器(验证集清单生成与出口
python tools/extract_checks.py --list-funcs [--src <源文件>...]
只打印函数清单与各函数条数(编账本辅助,不写文件)
断言源(--src 可多个;缺省=三宿主遍历):
game/tests/unit/**/*.gd + game/tests/integration/**/*.gd + game/tests/system_test.gd
断言源(--src 可多个;缺省=单元层遍历):
game/tests/unit/**/*.gd + game/tests/system_test.gd
批 B 出口对账用显式模式(--src 列全本批宿主文件)——缺省遍历含既有套件的 Kit.check
断言,对账时以「新增」出现(非迁移面),出口判定以显式模式为准。
提取口径:
- 静态断言调用点,三通道都认:smoke/系统宿主的 check(cond, label)(cond 在前)、
单元/集成宿主的 Kit.check("label", cond)(点前缀=标签在前)、静默收集通道
单元宿主的 Kit.check("label", cond)(点前缀=标签在前)、静默收集通道
Kit.check_quiet(cond, label)(cond 在前,条目 quiet 列记 channel:check_quiet);
`_check(` 等同名前缀调用非标准通道,不取。
- 调用点可跨行:从调用名起括号配平归集完整实参文本(() [] {} 三种括号都计深度);
@@ -45,18 +45,17 @@ from datetime import date
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
# 断言源缺省=三宿主遍历:unit/**+integration/** 两目录递归 + 系统宿主单文件。
# 断言源缺省=单元层目录递归 + 系统宿主单文件(跨系统闭环套件同住 unit/,随目录递归收进来)。
# 遍历面含既有套件的 Kit.check 断言(非本批迁移面,对账呈「新增」)——出口对账用 --src 显式列宿主。
DEFAULT_TREES = (
ROOT / "game" / "tests" / "unit",
ROOT / "game" / "tests" / "integration",
ROOT / "game" / "tests" / "system_test.gd",
)
DEFAULT_OUT = ROOT / "game" / "tests" / "验证集清单.md"
def default_sources():
"""三宿主遍历:两目录递归 *.gd + 系统宿主单文件,路径排序定序。"""
"""单元层遍历:unit 目录递归 *.gd + 系统宿主单文件,路径排序定序。"""
files = []
for p in DEFAULT_TREES:
if p.is_file():
@@ -342,7 +341,7 @@ def render_list(entries, funcs_by_src, src_names, carry=None) -> str:
out.append("")
out.append("> 生成日期:%s · 基点 commit:`%s` · 源:%s" % (date.today().isoformat(), base_commit(), "、".join(src_names)))
out.append("> 提取口径:静态 `check(`/`check_quiet(` 调用点,括号配平归集(可跨行);缺省源=三宿主遍历")
out.append("> (unit/**+integration/**+system_test.gd)。本基点实测 %d 个静态调用点;行级" % len(entries))
out.append("> (unit/**+system_test.gd)。本基点实测 %d 个静态调用点;行级" % len(entries))
out.append("> `grep -c \"check(\"` 是另一口径(含 `func check(` 定义行与注释行),两口径各自浮动,")
out.append("> 禁互相换算(tests/README「断言计数双口径」)。运行时计数大于静态计数=循环展开条目。")
out.append("> 生成命令:`python tools/extract_checks.py --extract`(可复现;重新生成须 --force;")
@@ -558,7 +557,7 @@ def main() -> int:
ap.add_argument("--diff", metavar="清单文件", help="与清单逐条对账(批 B 出口机检)")
ap.add_argument("--list-funcs", action="store_true", help="打印函数清单与条数(编账本辅助)")
ap.add_argument("--src", nargs="+", default=None,
help="断言源文件(可多个;缺省=三宿主遍历 unit/**+integration/**+system_test.gd)")
help="断言源文件(可多个;缺省=单元层遍历 unit/**+system_test.gd)")
ap.add_argument("--out", default=str(DEFAULT_OUT), help="--extract 输出路径")
ap.add_argument("--force", action="store_true", help="输出文件已存在时允许覆盖")
ap.add_argument("--carry-from", default=None, metavar="旧清单",
+15 -15
View File
@@ -10,16 +10,16 @@
# 跑闸时代码面带着未提交改动,回执会标 dirty_game(验的不是 HEAD 字节)。
#
# 用法:tools/run_all_gates.sh [--code|--docs|--gates|--premerge|--quick]
# --premerge 合回前置检查档(2026-11-06 用户裁):只跑冒烟测试+单元与集成测试全套件(4 分片,
# --premerge 合回前置检查档(2026-11-06 用户裁):只跑冒烟测试+单元测试全套件(4 分片,
# 热导入缓存约 2 分钟)——主工作区 git merge --no-ff 落合并提交前由 pre-merge-commit
# 钩子自动调用的拦截面。退出码聚合即判定(三硬闸口径),不落回执、不比基线——
# 验证台账归合回后远端 CI,本档只做当场拦截。快进合并不触发钩子;--no-verify 仅属用户。
# --code 只跑代码域闸(冒烟测试/系统测试/单元与集成测试/场景探针/
# --code 只跑代码域闸(冒烟测试/系统测试/单元测试/场景探针/
# 渲染闸/静态扫描+熵增闸)
# ——本批改动含 game/ 下非 .md 的行为载体(代码/测试脚本/探针/场景/数据表/素材)时用。
# 关联档选闸(2026-10-29 用户裁,推广自 2026-10-28 影响面选闸):冒烟测试/系统测试/
# 静态扫描三件保险恒跑不降;场景探针与渲染闸维持影响面口径(本批 game/ 改动
# 全在测量面 game/tests、game/sim 时记 SKIP);单元与集成测试改「选套件跑」——套件集=
# 全在测量面 game/tests、game/sim 时记 SKIP);单元测试改「选套件跑」——套件集=
# 需求卡片申报 ∪ diff 推导并集(算法与套件族映射表见脚本中部),横切面(公共件/数据表/
# autoload/数值·存档·RNG·结算触面)回落全套件;回执 scope 字段记 full|related。
# --docs 只跑文档域闸(gdd_lint/doc_link/doc_term/流水线闸/引用可核/
@@ -198,9 +198,9 @@ suite_terms_for() { # suite_terms_for <仓库相对路径> → stdout: 套件
game/core/meta_state_store.gd|game/core/slot_store.gd|game/core/gp_wallet.gd|\
game/core/shop_session.gd)
echo "core" ;;
# 冒险结构×存档断点×关卡推进(core 族+跨系统集成族)
# 冒险结构×存档断点×关卡推进(core 族+跨系统闭环族——三套件按文件名词选)
game/core/adventure_runner.gd|game/core/level_runner.gd)
echo "core integration" ;;
echo "core save_rng cross_system node_map" ;;
# 配置域表类(autoload 本体与解析器/跨表校验器走横切,不入本表)
game/core/config_domain_*.gd)
echo "data_config core" ;;
@@ -222,7 +222,7 @@ suite_terms_for() { # suite_terms_for <仓库相对路径> → stdout: 套件
# 三件保险恒跑不降:冒烟测试/系统测试/静态扫描(熵增闸照旧两域都跑)。
# 场景探针与渲染闸维持影响面口径:本批 diff 相对 master 分叉点的 game/ 改动若全部落在
# 测量面(game/tests/**、game/sim/**——测试与模拟驱动件,不触场景树与渲染输出)则记 SKIP。
# 单元与集成测试改「选套件跑」:套件集=申报 ∪ 推导 取并集——
# 单元测试改「选套件跑」:套件集=申报 ∪ 推导 取并集——
# 申报:在册需求卡片(本批 diff 触及的 reports/需求卡片*.md ∪ roadmap「进行中」迭代行登记的
# 卡片)对照表「验收测试」列提到的测试文件名,按文件名作为 --only 子串词归套件;
# 找不到在册卡片则申报集为空并输出注明。
@@ -230,9 +230,9 @@ suite_terms_for() { # suite_terms_for <仓库相对路径> → stdout: 套件
# 映射不到的文件一律按横切处理。
# 横切回落全量:diff 命中 game/data/tables/**、公共件前缀(config_db*/rng_service*/
# save_manager*/meta_progression*/main*——main* 覆盖组合根拆件与主场景)、
# autoload 注册面(game/project.godot)、或下方横切触面表任一 → 单元与集成测试跑全部套件。
# 测量面批(game/ 改动全在 tests/sim):单元与集成测试照旧全套件跑(不加过滤)。
# 回执 scope 字段:full|related(单元与集成测试跑子集=related);映射表只在本脚本一处定义。
# autoload 注册面(game/project.godot)、或下方横切触面表任一 → 单元测试跑全部套件。
# 测量面批(game/ 改动全在 tests/sim):单元测试照旧全套件跑(不加过滤)。
# 回执 scope 字段:full|related(单元测试跑子集=related);映射表只在本脚本一处定义。
NONBEHAVIOR=0
SCOPE="full"
ONLY_TERMS=""
@@ -245,7 +245,7 @@ if in_domain code; then
NONBEHAVIOR=1
echo "[gates] 影响面选闸:game/ 改动全在测量面(tests/sim)——场景探针/渲染闸 → SKIP(冒烟测试/系统测试/静态扫描三件保险恒跑)"
fi
# ── 选套件推导(只对行为面代码文件做——测量面文件不进推导,其验证就是单元与集成测试/静态扫描自身)──
# ── 选套件推导(只对行为面代码文件做——测量面文件不进推导,其验证就是单元测试/静态扫描自身)──
_codefiles="$(echo "$_gfiles" | grep -viE '\.md$' | grep -vE '^(game/tests/|game/sim/)' || true)"
if [ -n "$_codefiles" ]; then
CROSSCUT=0
@@ -281,7 +281,7 @@ if in_domain code; then
done
if [ "$CROSSCUT" -eq 1 ]; then
SCOPE="full"
echo "[gates] 关联档选闸:diff 命中横切面(公共件/数据表/autoload/数值·存档·RNG·结算触面)——单元与集成测试回落全部套件"
echo "[gates] 关联档选闸:diff 命中横切面(公共件/数据表/autoload/数值·存档·RNG·结算触面)——单元测试回落全部套件"
else
# 并集去重:推导族词 ∪ 申报测试文件名;并集非空才过滤(映射表保证族词非空,此处双保险)。
_union="$(printf '%s\n' $_family_terms $_declared_names | sed '/^$/d' | sort -u | tr '\n' ' ' || true)"
@@ -297,7 +297,7 @@ if in_domain code; then
echo "[gates] 关联档选闸·申报:未找到在册需求卡片(diff 与 roadmap 进行中行均无),申报集为空——仅按 diff 推导"
fi
if [ "$SCOPE" = related ]; then
echo "[gates] 关联档选闸:单元与集成测试选套件跑(--only=${ONLY_TERMS})"
echo "[gates] 关联档选闸:单元测试选套件跑(--only=${ONLY_TERMS})"
fi
fi
fi
@@ -344,7 +344,7 @@ gate() { # gate <名称> <日志名> <命令...>
}
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分片态=多 Godot 进程各跑一片
local name="单元与集成测试"
local name="单元测试"
# 关联档选跑:把套件词列表经 --only= 传给 run_all(闸机来源标记 --only-source=gates,
# 入口据此打关联档横幅、不落「仅供开发期」免责句);全量态不传任何选跑参数。
local -a _user_args=()
@@ -448,7 +448,7 @@ gate_shell_selfcheck() {
}
# ══ 合回前置检查档(premerge,2026-11-06 用户裁)══
# 冒烟+单元与集成全套件(4 分片)——合回 merge 点的最小人工拦截面;不是全量、不替代远端 CI。
# 冒烟+单元全套件(4 分片)——合回 merge 点的最小人工拦截面;不是全量、不替代远端 CI。
# 选闸推导整段跳过(本档不按 diff 选闸——合回是最后拦截点,恒全套件);退出码聚合即判定,
# 不落回执不比基线(回执与基线面归远端 CI,本档读数只进合并现场)。
if [ "$DOMAIN" = "premerge" ]; then
@@ -463,7 +463,7 @@ if in_domain code; then
gate "冒烟测试" "smoke_boot.log" "$PY" "$REPO/tools/run_smoke.py"
# ── 系统测试(真实玩法路径断言面;宿主=game/tests/system_test.gd,缺省 --script 由 run_system_test.py 持有)──
gate "系统测试" "system_test.log" "$PY" "$REPO/tools/run_system_test.py"
# ── 单元与集成测试 ──
# ── 单元测试 ──
gate_unit
# ── 场景探针(走查+断言十件一次跑齐;iter27 漏跑断言段事故后固化为无条件整闸)──
if [ $NONBEHAVIOR -eq 1 ]; then