refactor: enhance test framework with automated resource tracking and scripted error capture capabilities
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
extends GutTest
|
||||
|
||||
# =============================================================================
|
||||
# Test: Gauntlet Candidate Scoring System (v2) [Gauntlet #073]
|
||||
# Covers each score component, camping accumulation, and full-formula
|
||||
# composition. Runs headless (no multiplayer peer), so elapsed_time = 0 and
|
||||
# the final-30s window is inactive unless a test sets elapsed_time directly.
|
||||
# =============================================================================
|
||||
|
||||
const GauntletManager = preload("res://scripts/managers/gauntlet_manager.gd")
|
||||
var manager
|
||||
var main_mock: Node
|
||||
var gridmap_mock: Node
|
||||
|
||||
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)
|
||||
manager = GauntletManager.new()
|
||||
main_mock.add_child(manager)
|
||||
manager.initialize(main_mock, gridmap_mock)
|
||||
manager.current_phase = 0
|
||||
|
||||
func after_each():
|
||||
if main_mock:
|
||||
main_mock.queue_free()
|
||||
|
||||
# =============================================================================
|
||||
# LayerPriority
|
||||
# =============================================================================
|
||||
|
||||
func test_layer_priority_matches_phase_weights():
|
||||
manager.current_phase = 0
|
||||
# Outer ring cell (corner-ish) gets the phase-0 outer weight (+60).
|
||||
assert_eq(manager._score_layer_priority(Vector2i(2, 2)), 60.0, "Phase 0 outer = +60")
|
||||
# Inner cell near center gets phase-0 inner weight (-40).
|
||||
assert_eq(manager._score_layer_priority(Vector2i(9, 8)), -40.0, "Phase 0 inner = -40")
|
||||
|
||||
func test_layer_priority_phase3_inner():
|
||||
manager.current_phase = 2
|
||||
assert_eq(manager._score_layer_priority(Vector2i(9, 8)), 60.0, "Phase 2 inner = +60")
|
||||
|
||||
# =============================================================================
|
||||
# StickyNeighbor
|
||||
# =============================================================================
|
||||
|
||||
func test_sticky_neighbor_score_scales():
|
||||
assert_eq(manager._score_sticky_neighbor(Vector2i(5, 5)), 0.0, "No neighbors = 0")
|
||||
manager.sticky_cells[Vector2i(5, 6)] = true
|
||||
assert_eq(manager._score_sticky_neighbor(Vector2i(5, 5)), 8.0, "One neighbor = +8")
|
||||
|
||||
func test_sticky_neighbor_score_capped():
|
||||
# Surround (5,5) on all 8 sides → 8 * 8 = 64, capped at 64.
|
||||
for dx in range(-1, 2):
|
||||
for dz in range(-1, 2):
|
||||
if dx == 0 and dz == 0:
|
||||
continue
|
||||
manager.sticky_cells[Vector2i(5 + dx, 5 + dz)] = true
|
||||
assert_eq(manager._score_sticky_neighbor(Vector2i(5, 5)), 64.0, "Capped at +64")
|
||||
|
||||
# =============================================================================
|
||||
# InwardPressure
|
||||
# =============================================================================
|
||||
|
||||
func test_inward_pressure_higher_near_center():
|
||||
manager.current_phase = 2
|
||||
var near = manager._score_inward_pressure(Vector2i(8, 8)) # close to center
|
||||
var far = manager._score_inward_pressure(Vector2i(1, 1)) # far corner
|
||||
assert_true(near > far, "Inward pressure stronger near center")
|
||||
|
||||
func test_inward_pressure_phase_scaling():
|
||||
# Same cell, later phase => higher inward pressure ceiling.
|
||||
var pos := Vector2i(8, 8)
|
||||
manager.current_phase = 0
|
||||
var p0 = manager._score_inward_pressure(pos)
|
||||
manager.current_phase = 2
|
||||
var p2 = manager._score_inward_pressure(pos)
|
||||
assert_true(p2 > p0, "Later phase pushes inward harder")
|
||||
|
||||
# =============================================================================
|
||||
# PlayerPressure
|
||||
# =============================================================================
|
||||
|
||||
func test_player_pressure_ring():
|
||||
# 3 cells from a player → +20.
|
||||
var players = [Vector2i(5, 5)]
|
||||
assert_eq(manager._score_player_pressure(Vector2i(8, 5), players), 20.0, "2-4 cells away = +20")
|
||||
|
||||
func test_player_pressure_under_player_penalized():
|
||||
var players = [Vector2i(5, 5)]
|
||||
# elapsed_time 0, round 180 → not final window → directly under = -50.
|
||||
assert_eq(manager._score_player_pressure(Vector2i(5, 5), players), -50.0, "Under player (early) = -50")
|
||||
|
||||
func test_player_pressure_under_player_final_window():
|
||||
manager.elapsed_time = manager.gauntlet_round_duration() - 5.0 # within final 30s
|
||||
var players = [Vector2i(5, 5)]
|
||||
assert_eq(manager._score_player_pressure(Vector2i(5, 5), players), 10.0, "Under player (final) = +10")
|
||||
|
||||
func test_player_pressure_no_players():
|
||||
assert_eq(manager._score_player_pressure(Vector2i(5, 5), []), 0.0, "No players = 0")
|
||||
|
||||
# =============================================================================
|
||||
# ClusterGrowth
|
||||
# =============================================================================
|
||||
|
||||
func test_cluster_growth_none():
|
||||
assert_eq(manager._score_cluster_growth(Vector2i(5, 5)), 0.0, "No sticky neighbors = 0")
|
||||
|
||||
func test_cluster_growth_expand():
|
||||
manager.sticky_cells[Vector2i(5, 6)] = true
|
||||
assert_eq(manager._score_cluster_growth(Vector2i(5, 5)), 15.0, "Expanding cluster = +15")
|
||||
|
||||
func test_cluster_growth_connect():
|
||||
manager.sticky_cells[Vector2i(4, 5)] = true
|
||||
manager.sticky_cells[Vector2i(6, 5)] = true
|
||||
manager.sticky_cells[Vector2i(5, 6)] = true
|
||||
assert_eq(manager._score_cluster_growth(Vector2i(5, 5)), 25.0, "Connecting clusters = +25")
|
||||
|
||||
# =============================================================================
|
||||
# CampingPressure
|
||||
# =============================================================================
|
||||
|
||||
func test_camp_region_grouping():
|
||||
assert_eq(manager._region_of(Vector2i(0, 0)), Vector2i(0, 0), "Cells 0-3 → region 0")
|
||||
assert_eq(manager._region_of(Vector2i(5, 7)), Vector2i(1, 1), "Cells 4-7 → region 1")
|
||||
|
||||
func test_camping_pressure_thresholds():
|
||||
var region: Vector2i = manager._region_of(Vector2i(8, 8))
|
||||
manager._camp_tracking[1] = {"region": region, "time": 6.0}
|
||||
assert_eq(manager._score_camping_pressure(Vector2i(8, 8)), 20.0, ">5s = +20")
|
||||
manager._camp_tracking[1]["time"] = 9.0
|
||||
assert_eq(manager._score_camping_pressure(Vector2i(8, 8)), 40.0, ">8s = +40")
|
||||
manager._camp_tracking[1]["time"] = 11.0
|
||||
assert_eq(manager._score_camping_pressure(Vector2i(8, 8)), 60.0, ">10s = +60")
|
||||
|
||||
func test_camping_pressure_none():
|
||||
assert_eq(manager._score_camping_pressure(Vector2i(8, 8)), 0.0, "No camping = 0")
|
||||
|
||||
# =============================================================================
|
||||
# Repetition
|
||||
# =============================================================================
|
||||
|
||||
func test_repetition_penalty():
|
||||
manager._last_tick_cells = [Vector2i(5, 5)]
|
||||
assert_eq(manager._score_repetition(Vector2i(5, 6)), -30.0, "Adjacent to last tick = -30")
|
||||
assert_eq(manager._score_repetition(Vector2i(15, 15)), 0.0, "Far from last tick = 0")
|
||||
|
||||
# =============================================================================
|
||||
# PathSafety (soft penalty)
|
||||
# =============================================================================
|
||||
|
||||
func test_path_safety_no_players_no_penalty():
|
||||
assert_eq(manager._score_path_safety(Vector2i(5, 5)), 0.0, "No players = no penalty")
|
||||
|
||||
# =============================================================================
|
||||
# Camp tracking accumulation
|
||||
# =============================================================================
|
||||
|
||||
func test_camp_time_for_region_picks_max():
|
||||
var region := Vector2i(1, 1)
|
||||
manager._camp_tracking[1] = {"region": region, "time": 3.0}
|
||||
manager._camp_tracking[2] = {"region": region, "time": 7.0}
|
||||
assert_almost_eq(manager._camp_time_for_region(region), 7.0, 0.001, "Longest camp time wins")
|
||||
|
||||
# =============================================================================
|
||||
# Full formula composition
|
||||
# =============================================================================
|
||||
|
||||
func test_full_score_runs_and_is_finite():
|
||||
var s = manager._calculate_candidate_score(Vector2i(5, 5), [])
|
||||
assert_true(is_finite(s), "Full score is a finite number")
|
||||
|
||||
func test_full_score_rewards_sticky_cluster():
|
||||
# A cell hugging an existing cluster should generally beat an isolated one.
|
||||
# Average several samples to wash out RandomNoise (±20).
|
||||
manager.sticky_cells[Vector2i(5, 6)] = true
|
||||
manager.sticky_cells[Vector2i(6, 5)] = true
|
||||
var clustered := 0.0
|
||||
var isolated := 0.0
|
||||
for _i in range(40):
|
||||
clustered += manager._calculate_candidate_score(Vector2i(5, 5), [])
|
||||
isolated += manager._calculate_candidate_score(Vector2i(15, 15), [])
|
||||
assert_true(clustered > isolated, "Clustered cell scores higher on average")
|
||||
Reference in New Issue
Block a user