T6 探针基建收口段: 三族样板收单点(probe_ui_util树寻址contains/begins_with参数化+isolate_save七份隔离样板/battle_driver五份战斗驱动)+level_autoplay双战斗循环合并_decide_act+test_kit收13套件_check样板(断言数逐套件零丢失对照表在报告)+BAD_DIR夹具共享+smoke_all五件(:953公有面clamped_pool/_battle_st七袋/check_silent并入quiet参/_pct转发删/load改preload);探针小件=main句柄Node类型注/魔法等待常量化/画布常数同源锚注/死参verbose删;红线守住=ui_input case④b与click循环体零触碰/拍板点三件未退役
This commit is contained in:
1 parent
0691a188fd
commit
315e46038c
32 files changed
+587
-764
No files matched your search
@@ -3,6 +3,17 @@ extends SceneTree
|
||||
# 原守 node_overlay.show_reward_items;奖励节点三选一与通关三选一合并共用 BonusPickOverlay 后,
|
||||
# 本套件改守共用面的「功能存在 ≠ 功能可达」盲区:选择外发/强制确认两段式/替换子面板两路/结果态。
|
||||
# 运行:godot --headless --path game --script res://tests/unit/presentation/reward_overlay_test.gd(expect 0)
|
||||
# T6 收口批:断言走 test_kit 计数(Kit.check)+ 失败即停早退协议保留(顺序状态机——坏态下后继断言无效)。
|
||||
const Kit := preload("res://tests/unit/test_kit.gd")
|
||||
|
||||
# 断言 + 失败即停(原直写 print FAIL + quit(1) + return 样板单点化——早退语义逐位保持)
|
||||
func _req(desc: String, ok: bool) -> bool:
|
||||
Kit.check(desc, ok)
|
||||
if not ok:
|
||||
quit(1)
|
||||
return false
|
||||
return true
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
@@ -25,17 +36,15 @@ func _run() -> void:
|
||||
for c in ov._choice_box.get_children():
|
||||
if c is Button:
|
||||
btns += 1
|
||||
if ov.visible != true or btns != 3 or ov._confirm_btn.visible or ov._continue_btn.visible:
|
||||
print("[reward_verify] FAIL — 选择态应三卡呈现且确认/继续隐藏(btns=%d)" % btns)
|
||||
quit(1)
|
||||
if not _req("选择态应三卡呈现且确认/继续隐藏(btns=%d)" % btns,
|
||||
ov.visible and btns == 3 and not ov._confirm_btn.visible and not ov._continue_btn.visible):
|
||||
return
|
||||
# ② 点选→高亮→确认外发(真实按钮路径);确认前改选以最后点选为准
|
||||
ov.press_card(0)
|
||||
ov.press_card(1)
|
||||
ov.press_confirm()
|
||||
if ov._confirm_btn.visible != true or picked.size() != 1 or String(picked[0]) != "gp":
|
||||
print("[reward_verify] FAIL — 点选确认未外发 pick_confirmed(gp)(%s)" % str(picked))
|
||||
quit(1)
|
||||
if not _req("点选确认未外发 pick_confirmed(gp)(%s)" % str(picked),
|
||||
ov._confirm_btn.visible and picked.size() == 1 and String(picked[0]) == "gp"):
|
||||
return
|
||||
# ③ 替换子面板:丢旧收新与放弃新件两路外发(通关渠道=携带序号 / 节点渠道=库存句柄——tag 直通)
|
||||
ov.open_replace([{"index": 0, "item_id": "probe_dust", "display_name": "显影尘"}], "爆破工兵包", 1, 1)
|
||||
@@ -43,33 +52,26 @@ func _run() -> void:
|
||||
for c in ov._replace_box.get_children():
|
||||
if c is Button:
|
||||
replace_btns += 1
|
||||
if replace_btns != 2 or ov._choice_box.visible:
|
||||
print("[reward_verify] FAIL — 替换面板应 2 钮(N+1 选 N+放弃)且三卡隐藏(btns=%d)" % replace_btns)
|
||||
quit(1)
|
||||
if not _req("替换面板应 2 钮(N+1 选 N+放弃)且三卡隐藏(btns=%d)" % replace_btns,
|
||||
replace_btns == 2 and not ov._choice_box.visible):
|
||||
return
|
||||
var replaced_first := false
|
||||
for c in ov._replace_box.get_children():
|
||||
if c is Button:
|
||||
c.pressed.emit()
|
||||
replaced_first = true
|
||||
break
|
||||
if replaced.size() != 1 or int(replaced[0]) != 0:
|
||||
print("[reward_verify] FAIL — 丢旧收新未外发 replace_chosen(0)(%s)" % str(replaced))
|
||||
quit(1)
|
||||
if not _req("丢旧收新未外发 replace_chosen(0)(%s)" % str(replaced),
|
||||
replaced_first and replaced.size() == 1 and int(replaced[0]) == 0):
|
||||
return
|
||||
# ④ 结果态:继续钮点亮、唯一出口
|
||||
ov.show_result("已选择:攻击力提升 · 攻击 +1")
|
||||
if ov._continue_btn.visible != true or ov._replace_box.visible:
|
||||
print("[reward_verify] FAIL — 结果态应点亮继续且收替换面板")
|
||||
quit(1)
|
||||
if not _req("结果态应点亮继续且收替换面板", ov._continue_btn.visible and not ov._replace_box.visible):
|
||||
return
|
||||
ov.press_continue()
|
||||
if continued.size() != 1:
|
||||
print("[reward_verify] FAIL — 继续未外发 continue_pressed")
|
||||
quit(1)
|
||||
if not _req("继续未外发 continue_pressed", continued.size() == 1):
|
||||
return
|
||||
ov.close_pick()
|
||||
if ov.visible:
|
||||
print("[reward_verify] FAIL — close_pick 应收屏")
|
||||
quit(1)
|
||||
if not _req("close_pick 应收屏", not ov.visible):
|
||||
return
|
||||
print("[reward_verify] PASS — 三卡两段式/确认外发/替换两路/结果态/收屏 全过")
|
||||
quit(0)
|
||||
quit(Kit.finish("reward_verify", "PASS — 三卡两段式/确认外发/替换两路/结果态/收屏 全过"))
|
||||
@@ -9,9 +9,7 @@ extends SceneTree
|
||||
|
||||
const ConfigDBScript := preload("res://core/config_db.gd")
|
||||
const BoardViewScript := preload("res://presentation/views/board_view.gd")
|
||||
|
||||
var _failures := 0
|
||||
var _checks := 0
|
||||
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
@@ -23,7 +21,7 @@ func _init() -> void:
|
||||
return
|
||||
var db = ConfigDBScript.new()
|
||||
var load_ok: bool = db.load_tables("res://data/tables", true)
|
||||
_check("前置:表加载零 error", load_ok and db.diagnostics_count("error") == 0)
|
||||
Kit.check("前置:表加载零 error", load_ok and db.diagnostics_count("error") == 0)
|
||||
if not load_ok:
|
||||
quit(1)
|
||||
return
|
||||
@@ -33,25 +31,11 @@ func _init() -> void:
|
||||
var bt := String(row.get("board_type", ""))
|
||||
if bt != "" and not types.has(bt):
|
||||
types.append(bt)
|
||||
_check("前置:board_gen 词表非空(%d 型)" % types.size(), types.size() > 0)
|
||||
Kit.check("前置:board_gen 词表非空(%d 型)" % types.size(), types.size() > 0)
|
||||
_test_set_completeness(board_dir, types)
|
||||
_test_hue_domains(board_dir)
|
||||
_test_digit_ink_modes(board_dir, types)
|
||||
if _failures > 0:
|
||||
push_error("[terrain_tile_sets_test] %d/%d 项失败" % [_failures, _checks])
|
||||
quit(1)
|
||||
return
|
||||
print("[terrain_tile_sets_test] all green (%d checks)" % _checks)
|
||||
quit(0)
|
||||
|
||||
|
||||
func _check(desc: String, ok: bool) -> void:
|
||||
_checks += 1
|
||||
if ok:
|
||||
print(" [PASS] " + desc)
|
||||
else:
|
||||
_failures += 1
|
||||
push_error(" [FAIL] " + desc)
|
||||
quit(Kit.finish("terrain_tile_sets_test"))
|
||||
|
||||
|
||||
# 套完整性:词表每个 board_type 的 16 墙 + 5 地面变体全部在盘(缺位 → BoardView 整批回落 dungeon 的
|
||||
@@ -69,7 +53,7 @@ func _test_set_completeness(board_dir: String, types: Array) -> void:
|
||||
var pf := board_dir.path_join("terrain_floor_%s_%d.png" % [String(bt), i])
|
||||
if not FileAccess.file_exists(pf):
|
||||
missing.append("floor_%d" % i)
|
||||
_check("图型 %s 瓦片套完整(16 墙 + %d 地面,缺=%s)" % [String(bt), variants, str(missing)], missing.is_empty())
|
||||
Kit.check("图型 %s 瓦片套完整(16 墙 + %d 地面,缺=%s)" % [String(bt), variants, str(missing)], missing.is_empty())
|
||||
|
||||
|
||||
# 色相域抽检:wall_center 上半幅(墙顶面)与 floor_1 全幅的均值色相/明度
|
||||
@@ -85,17 +69,17 @@ func _test_hue_domains(board_dir: String) -> void:
|
||||
var wall := _load_stats(board_dir, "terrain_wall_center_%s.png" % String(bt), true)
|
||||
var floor_img := _load_stats(board_dir, "terrain_floor_%s_1.png" % String(bt), false)
|
||||
if wall.is_empty() or floor_img.is_empty():
|
||||
_check("图型 %s 抽检样本可读" % String(bt), false)
|
||||
Kit.check("图型 %s 抽检样本可读" % String(bt), false)
|
||||
continue
|
||||
wall_v[bt] = float(wall["v"])
|
||||
floor_v[bt] = float(floor_img["v"])
|
||||
var band: Array = bands[bt]
|
||||
_check("图型 %s 墙顶均值色相在带 %s(实测 %.3f)" % [String(bt), str(band), float(wall["h"])],
|
||||
Kit.check("图型 %s 墙顶均值色相在带 %s(实测 %.3f)" % [String(bt), str(band), float(wall["h"])],
|
||||
float(wall["h"]) >= float(band[0]) and float(wall["h"]) <= float(band[1]))
|
||||
_check("图型 %s 图底分离(墙顶明度 %.3f > 地面 %.3f)" % [String(bt), wall_v[bt], floor_v[bt]],
|
||||
Kit.check("图型 %s 图底分离(墙顶明度 %.3f > 地面 %.3f)" % [String(bt), wall_v[bt], floor_v[bt]],
|
||||
wall_v[bt] > floor_v[bt])
|
||||
if wall_v.has("underdark") and wall_v.has("deep_underdark"):
|
||||
_check("deep_underdark 墙顶更暗于 underdark(更深蓝黑方向)", float(wall_v["deep_underdark"]) < float(wall_v["underdark"]))
|
||||
Kit.check("deep_underdark 墙顶更暗于 underdark(更深蓝黑方向)", float(wall_v["deep_underdark"]) < float(wall_v["underdark"]))
|
||||
|
||||
|
||||
# 均值读数:hue 取饱和度 > 0.05 的像素(墨线/灰黑不影响色相均值);v 取全幅均值
|
||||
@@ -150,26 +134,26 @@ func _test_digit_ink_modes(board_dir: String, types: Array) -> void:
|
||||
var tex: Texture2D = ImageTexture.create_from_image(Image.load_from_file(p))
|
||||
BoardViewScript._normalize_floor_luma(tex, 0.10, lumas)
|
||||
if not readable:
|
||||
_check("图型 %s 数字墨族断言样本可读" % String(bt), false)
|
||||
Kit.check("图型 %s 数字墨族断言样本可读" % String(bt), false)
|
||||
continue
|
||||
var mode: Dictionary = BoardViewScript._digit_ink_mode(lumas)
|
||||
var plate: bool = bool(mode["plate"])
|
||||
var dark: bool = bool(mode["dark"])
|
||||
var mode_name := "色牌垫底" if plate else ("深墨族直画" if dark else "亮墨族直画")
|
||||
if plate:
|
||||
_check("图型 %s 双峰纹理落牌(亮族 p90 %.2f/均值 %.2f,深族 p90 %.2f/均值 %.2f 均未过门)" % [
|
||||
Kit.check("图型 %s 双峰纹理落牌(亮族 p90 %.2f/均值 %.2f,深族 p90 %.2f/均值 %.2f 均未过门)" % [
|
||||
String(bt), float(mode["cr_p90_bright"]), float(mode["cr_mean_bright"]),
|
||||
float(mode["cr_p90_dark"]), float(mode["cr_mean_dark"])],
|
||||
float(mode["cr_mean_dark"]) < float(BoardViewScript.DIGIT_INK_CR_MEAN_DARK))
|
||||
else:
|
||||
var cr_p90 := float(mode["cr_p90_bright"]) if not dark else float(mode["cr_p90_dark"])
|
||||
var cr_mean := float(mode["cr_mean_bright"]) if not dark else float(mode["cr_mean_dark"])
|
||||
_check("图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" % [String(bt), mode_name,
|
||||
Kit.check("图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" % [String(bt), mode_name,
|
||||
float(BoardViewScript.DIGIT_INK_CR_P90), cr_p90],
|
||||
cr_p90 >= float(BoardViewScript.DIGIT_INK_CR_P90))
|
||||
var mean_gate := float(BoardViewScript.DIGIT_INK_CR_MEAN_BRIGHT) if not dark else float(BoardViewScript.DIGIT_INK_CR_MEAN_DARK)
|
||||
_check("图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" % [String(bt), mode_name, mean_gate, cr_mean],
|
||||
Kit.check("图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" % [String(bt), mode_name, mean_gate, cr_mean],
|
||||
cr_mean >= mean_gate)
|
||||
if expect_plate.has(bt):
|
||||
_check("图型 %s 呈现模式期望=%s(实测=%s)" % [String(bt),
|
||||
Kit.check("图型 %s 呈现模式期望=%s(实测=%s)" % [String(bt),
|
||||
"色牌" if bool(expect_plate[bt]) else "直画", mode_name], plate == bool(expect_plate[bt]))
|
||||
@@ -7,38 +7,22 @@
|
||||
extends SceneTree
|
||||
|
||||
const UiKitScript := preload("res://presentation/views/ui_kit.gd")
|
||||
|
||||
var _failures := 0
|
||||
var _checks := 0
|
||||
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var path: String = UiKitScript.FONT_UI
|
||||
var f: Font = UiKitScript.load_font(path)
|
||||
_check("随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)", f != null)
|
||||
Kit.check("随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)", f != null)
|
||||
if f != null:
|
||||
_check("中文字形在集(攻/雷/旗/封)", f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \
|
||||
Kit.check("中文字形在集(攻/雷/旗/封)", f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \
|
||||
and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0)))
|
||||
_check("ASCII/数字字形在集(A/0/%)", f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)))
|
||||
Kit.check("ASCII/数字字形在集(A/0/%)", f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)))
|
||||
var sz := 18
|
||||
var w_cn: float = f.get_string_size("战斗胜利", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x
|
||||
var w_label: float = f.get_string_size("攻击 2", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x
|
||||
_check("中文采样文本宽度 > 0(C6 headless 判据)", w_cn > 0.0 and w_label > 0.0)
|
||||
Kit.check("中文采样文本宽度 > 0(C6 headless 判据)", w_cn > 0.0 and w_label > 0.0)
|
||||
# 注:不设「私用区 has_char=false」负探针——fusion pixel 实测覆盖 PUA 码位,负向覆盖非契约面(宁缺勿错)
|
||||
else:
|
||||
_check("字体缺失时后续断言跳过(缺位=回归,此行仅占位计数)", false)
|
||||
if _failures > 0:
|
||||
push_error("[ui_font_asset_test] %d/%d 项失败" % [_failures, _checks])
|
||||
quit(1)
|
||||
return
|
||||
print("[ui_font_asset_test] all green (%d checks)" % _checks)
|
||||
quit(0)
|
||||
|
||||
|
||||
func _check(desc: String, ok: bool) -> void:
|
||||
_checks += 1
|
||||
if ok:
|
||||
print(" [PASS] " + desc)
|
||||
else:
|
||||
_failures += 1
|
||||
push_error(" [FAIL] " + desc)
|
||||
Kit.check("字体缺失时后续断言跳过(缺位=回归,此行仅占位计数)", false)
|
||||
quit(Kit.finish("ui_font_asset_test"))
|
||||
Reference in new issue
Block a user