Files
tactical-shooter/tests/test_utils.gd
T
shawn e7299b17e9 Phase 7: netfox + godot-jolt stack upgrade
Stack installed:
- netfox v1.35.3 (core + extras + noray + internals)
- godot-jolt v0.16.0-stable

Architecture:
- Server: ENet transport (works headless, no netfox deps)
- Client/Editor: netfox rollback (RollbackSynchronizer, TickInterpolator)

New/modified:
- docs/migration-netfox-plan.md — migration architecture
- scripts/network/network_manager.gd — netfox-aware ENet fallback
- scripts/network/player.gd — clean base player
- client/characters/player_netfox.gd — rollback player w/ WeaponManager
- client/characters/input/player_net_input.gd — BaseNetInput subclass
- client/characters/character/fps_character_controller.gd — netfox input feed
- client/weapons/ — weapon data, registry, TacticalWeaponHitscan, WeaponManager
- client/scripts/round_replicator.gd — client-side round state bridge
- server/scripts/round_manager.gd — improved state machine
- server/scripts/plugin_api/plugin_manager.gd — refined plugin system
- config: enemy_tag, ally_tag for meatball targeting

Removed: old C++ SimulationServer GDExtension (replaced by netfox rollback)
2026-07-02 17:39:22 -04:00

112 lines
3.9 KiB
GDScript

extends Node
class_name TestUtils
# ═══════════════════════════════════════════════════════════════════════════
# TestUtils — Minimal assertion framework for headless Godot unit tests
#
# Usage:
# var tu = TestUtils.new()
# add_child(tu)
# tu.describe("Movement validation")
# tu.assert_eq(result.x, 5, "x should be 5")
# tu.assert_true(valid, "should be valid")
# tu.finish() # prints summary
# ═══════════════════════════════════════════════════════════════════════════
var _passed: int = 0
var _failed: int = 0
var _current_suite: String = ""
var _assertions_in_suite: int = 0
func describe(name: String) -> void:
"""Start a named test suite/section."""
_current_suite = name
_assertions_in_suite = 0
print("\n === " + name + " ===")
func assert_eq(got, expected, msg: String = "") -> void:
_assertions_in_suite += 1
if got == expected:
_passed += 1
else:
_failed += 1
var detail = "got '%s', expected '%s'" % [str(got), str(expected)]
print(" [FAIL] " + msg + "" + detail)
func assert_ne(got, unexpected, msg: String = "") -> void:
_assertions_in_suite += 1
if got != unexpected:
_passed += 1
else:
_failed += 1
print(" [FAIL] " + msg + " — got '%s' which matches unexpected value" % str(got))
func assert_true(cond: bool, msg: String = "") -> void:
_assertions_in_suite += 1
if cond:
_passed += 1
else:
_failed += 1
print(" [FAIL] " + msg + " — expected true, got false")
func assert_false(cond: bool, msg: String = "") -> void:
_assertions_in_suite += 1
if not cond:
_passed += 1
else:
_failed += 1
print(" [FAIL] " + msg + " — expected false, got true")
func assert_almost_eq(got: float, expected: float, tolerance: float = 0.001, msg: String = "") -> void:
_assertions_in_suite += 1
if abs(got - expected) <= tolerance:
_passed += 1
else:
_failed += 1
var detail = "got %.4f, expected %.4f ± %.4f" % [got, expected, tolerance]
print(" [FAIL] " + msg + "" + detail)
func assert_violation(result: Dictionary, category: int, msg: String = "") -> void:
"""Assert the validation result contains at least one violation of the given category."""
_assertions_in_suite += 1
for v in result.get("violations", []):
if v.get("category", -1) == category:
_passed += 1
return
_failed += 1
print(" [FAIL] " + msg + " — expected violation category " + str(category) + ", none found")
func assert_no_violation(result: Dictionary, msg: String = "") -> void:
"""Assert the validation result has zero violations."""
_assertions_in_suite += 1
var count = result.get("violations", []).size()
if count == 0:
_passed += 1
else:
_failed += 1
print(" [FAIL] " + msg + " — expected 0 violations, got " + str(count) + ": " + str(result["violations"]))
func assert_corrected(result: Dictionary, field: String, msg: String = "") -> void:
"""Assert the result's corrected dict has a different value for `field` than the original."""
_assertions_in_suite += 1
if result.get("corrected", {}).has(field):
_passed += 1
else:
_failed += 1
print(" [FAIL] " + msg + " — expected correction in field '%s', none found" % field)
func finish() -> void:
"""Print test summary and return exit code via OS."""
var total = _passed + _failed
print("\n ──────────────────────────────────────")
print(" Suite: " + _current_suite)
print(" Passed: %d / %d" % [_passed, total])
if _failed > 0:
print(" FAILED: %d test(s)" % _failed)
else:
print(" All passed.")
print("")
func exit_code() -> int:
return 0 if _failed == 0 else 1