refactor: enhance test framework with automated resource tracking and scripted error capture capabilities

This commit is contained in:
2026-06-26 09:40:17 +08:00
parent 948a99cf90
commit 00f9d98f4b
58 changed files with 3594 additions and 1289 deletions
+159
View File
@@ -0,0 +1,159 @@
extends GutTest
# =============================================================================
# Test: Gauntlet Growth Tick System (v2) [Gauntlet #067]
# Replaces the old cannon-timer test. Covers growth timing, phase configs,
# candidate generation, cells-per-tick ranges, weighted selection, and
# cleansed-cell exclusion.
# =============================================================================
const GauntletManager = preload("res://scripts/managers/gauntlet_manager.gd")
var gauntlet_manager: Node
var main_mock: Node
var gridmap_mock: Node
func before_all():
gut.p("=== Feature Tests [Gauntlet #067 Growth Tick] ===")
func before_each():
main_mock = Node.new()
add_child(main_mock)
gridmap_mock = Node.new()
gridmap_mock.name = "EnhancedGridMap"
main_mock.add_child(gridmap_mock)
gauntlet_manager = GauntletManager.new()
main_mock.add_child(gauntlet_manager)
gauntlet_manager.initialize(main_mock, gridmap_mock)
func after_each():
if main_mock:
main_mock.queue_free()
func after_all():
gut.p("=== Feature Tests Complete ===")
# =============================================================================
# Growth Timing
# =============================================================================
func test_growth_timer_starts_zero():
assert_eq(gauntlet_manager.growth_timer, 0.0, "Growth timer starts at 0.0")
func test_growth_interval_default():
assert_eq(gauntlet_manager.growth_interval, 3.0, "Growth interval defaults to 3.0s")
func test_telegraph_duration_default():
assert_eq(gauntlet_manager.telegraph_duration, 1.0, "Telegraph duration defaults to 1.0s")
# =============================================================================
# Phase Growth Config
# =============================================================================
func test_phase_growth_config_has_three_phases():
assert_eq(gauntlet_manager.phase_growth_config.size(), 3, "Three phase growth configs")
func test_phase1_cells_range():
var cfg = gauntlet_manager.phase_growth_config[0]
assert_eq(cfg["cells_min"], 4, "Phase 1 min 4 cells/tick")
assert_eq(cfg["cells_max"], 6, "Phase 1 max 6 cells/tick")
func test_phase2_cells_range():
var cfg = gauntlet_manager.phase_growth_config[1]
assert_eq(cfg["cells_min"], 6, "Phase 2 min 6 cells/tick")
assert_eq(cfg["cells_max"], 8, "Phase 2 max 8 cells/tick")
func test_phase3_cells_range():
var cfg = gauntlet_manager.phase_growth_config[2]
assert_eq(cfg["cells_min"], 8, "Phase 3 min 8 cells/tick")
assert_eq(cfg["cells_max"], 10, "Phase 3 max 10 cells/tick")
func test_cells_this_tick_in_phase_range():
for phase in range(3):
gauntlet_manager.current_phase = phase
var cfg = gauntlet_manager.phase_growth_config[phase]
# Sample several times since the count is randomized.
for _i in range(20):
var n = gauntlet_manager._cells_this_tick()
assert_true(n >= cfg["cells_min"] and n <= cfg["cells_max"],
"Phase %d cells/tick %d within [%d,%d]" % [phase, n, cfg["cells_min"], cfg["cells_max"]])
# =============================================================================
# Candidate Generation
# =============================================================================
func test_candidates_are_all_safe_cells():
gauntlet_manager.current_phase = 0
var candidates = gauntlet_manager._generate_candidates()
# Fresh arena: every playable cell is SAFE.
assert_eq(candidates.size(), gauntlet_manager.playable_cell_count(),
"All playable cells are candidates on a fresh arena")
func test_candidates_exclude_sticky():
gauntlet_manager.sticky_cells[Vector2i(3, 3)] = true
var candidates = gauntlet_manager._generate_candidates()
var found := false
for c in candidates:
if c["pos"] == Vector2i(3, 3):
found = true
assert_false(found, "Sticky cells are excluded from candidates")
func test_candidates_exclude_cleansed():
gauntlet_manager.mark_cleansed(Vector2i(4, 4))
var candidates = gauntlet_manager._generate_candidates()
var found := false
for c in candidates:
if c["pos"] == Vector2i(4, 4):
found = true
assert_false(found, "Cleansed cells are excluded from candidates (regrowth protection)")
func test_candidates_exclude_npc_and_boundary():
var candidates = gauntlet_manager._generate_candidates()
for c in candidates:
var p = c["pos"]
assert_false(gauntlet_manager._is_npc_zone(p), "No NPC-zone candidates")
assert_false(gauntlet_manager._is_boundary(p), "No boundary candidates")
func test_candidates_have_scores():
var candidates = gauntlet_manager._generate_candidates()
assert_true(candidates.size() > 0, "Has candidates")
assert_true(candidates[0].has("score"), "Candidate carries a score")
# =============================================================================
# Weighted Selection
# =============================================================================
func test_select_count_respected():
var candidates = gauntlet_manager._generate_candidates()
var picked = gauntlet_manager._select_cells_weighted(candidates, 5)
assert_eq(picked.size(), 5, "Selects exactly the requested count")
func test_select_no_duplicates():
var candidates = gauntlet_manager._generate_candidates()
var picked = gauntlet_manager._select_cells_weighted(candidates, 10)
var seen := {}
for p in picked:
assert_false(seen.has(p), "No duplicate selections")
seen[p] = true
func test_select_capped_at_pool_size():
var small = [{"pos": Vector2i(2, 2), "score": 1.0}, {"pos": Vector2i(2, 3), "score": 1.0}]
var picked = gauntlet_manager._select_cells_weighted(small, 10)
assert_eq(picked.size(), 2, "Cannot select more than pool size")
# =============================================================================
# Scoring Helpers
# =============================================================================
func test_layer_classification():
assert_eq(gauntlet_manager._layer_of(Vector2i(9, 9)), "inner", "Center is inner")
assert_eq(gauntlet_manager._layer_of(Vector2i(1, 1)), "outer", "Corner is outer")
func test_sticky_neighbor_count():
gauntlet_manager.sticky_cells[Vector2i(5, 5)] = true
gauntlet_manager.sticky_cells[Vector2i(5, 6)] = true
assert_eq(gauntlet_manager._sticky_neighbor_count(Vector2i(6, 5)), 2,
"Counts 8-directional sticky neighbors")
func test_chebyshev():
assert_eq(gauntlet_manager._chebyshev(Vector2i(0, 0), Vector2i(3, 1)), 3, "Chebyshev distance")