86 lines
3.1 KiB
GDScript
86 lines
3.1 KiB
GDScript
extends SceneTree
|
|
## Smoke test for the player character scene and its spawn behavior.
|
|
##
|
|
## Run with:
|
|
## godot --headless --path . --script res://scripts/smoke_test_player.gd
|
|
##
|
|
## Loads the test level, verifies the player is present, spawned at the
|
|
## PlayerSpawn marker, and has the expected CharacterBody3D structure.
|
|
|
|
var _passed := 0
|
|
var _failed := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
print("SMOKE: starting player smoke test")
|
|
_run()
|
|
|
|
|
|
func _run() -> void:
|
|
await process_frame
|
|
print("SMOKE: loading test level scene")
|
|
|
|
# Load the test level scene (which includes the player). Use the same
|
|
# SceneTree API as the real game so `current_scene` is populated before
|
|
# the scene is added and its _ready() callbacks fire. That ordering is
|
|
# what the player's spawn lookup (get_tree().current_scene) depends on.
|
|
var packed: PackedScene = load("res://scenes/worlds/test_level.tscn")
|
|
var result := change_scene_to_packed(packed)
|
|
if result != OK:
|
|
printerr("SMOKE: failed to change scene, error ", result)
|
|
quit(1)
|
|
return
|
|
|
|
await scene_changed
|
|
var level: Node3D = current_scene as Node3D
|
|
print("SMOKE: level ready")
|
|
|
|
# 1. Verify the player node exists in the scene tree.
|
|
var player: Node = level.get_node("Player")
|
|
_check("Player node exists in test level", player != null)
|
|
_check("Player is a CharacterBody3D", player is CharacterBody3D)
|
|
|
|
# 2. Verify the player has the expected child structure.
|
|
var collision: Node = player.get_node("CollisionShape3D")
|
|
_check("Player has CollisionShape3D", collision != null)
|
|
_check("CollisionShape3D has a shape",
|
|
collision is CollisionShape3D and (collision as CollisionShape3D).shape != null)
|
|
|
|
var mesh: Node = player.get_node("CapsuleMesh")
|
|
_check("Player has CapsuleMesh", mesh != null)
|
|
_check("CapsuleMesh has a mesh",
|
|
mesh is MeshInstance3D and (mesh as MeshInstance3D).mesh != null)
|
|
|
|
# 3. Verify the player spawned at the PlayerSpawn marker position.
|
|
var spawn_marker: Marker3D = level.get_node("PlayerSpawn")
|
|
_check("PlayerSpawn marker exists", spawn_marker != null)
|
|
|
|
# The player's _ready() should have moved it to the spawn marker's
|
|
# global position. Since both are direct children of the level root
|
|
# (and the level root is at the origin), their global positions equal
|
|
# their local positions.
|
|
var expected_pos: Vector3 = spawn_marker.global_position
|
|
_check("Player spawned at PlayerSpawn position",
|
|
player.global_position == expected_pos)
|
|
|
|
# 4. Verify the player script class_name is correct and has the
|
|
# movement constants defined.
|
|
var script: GDScript = player.get_script() as GDScript
|
|
_check("Player has a script attached", script != null)
|
|
var constants: Dictionary = script.get_script_constant_map()
|
|
_check("Player has WALK_SPEED constant", constants.has("WALK_SPEED"))
|
|
_check("Player has GRAVITY constant", constants.has("GRAVITY"))
|
|
_check("Player has JUMP_VELOCITY constant", constants.has("JUMP_VELOCITY"))
|
|
|
|
print("\n=== SMOKE RESULT: %d/%d passed ===" % [_passed, _passed + _failed])
|
|
quit(0 if _failed == 0 else 1)
|
|
|
|
|
|
func _check(description: String, condition: bool) -> void:
|
|
if condition:
|
|
print(" PASS: ", description)
|
|
_passed += 1
|
|
else:
|
|
printerr(" FAIL: ", description)
|
|
_failed += 1
|