refactor: enhance test framework with automated resource tracking and scripted error capture capabilities
This commit is contained in:
@@ -31,6 +31,34 @@ func suite_teardown() -> void:
|
||||
pass
|
||||
|
||||
|
||||
# ----- tracked allocations (freed by the runner after each test) -----
|
||||
|
||||
var _tracked_objects: Array[Object] = []
|
||||
|
||||
|
||||
## Register a manually-managed Object (plain Object or out-of-tree Node) so
|
||||
## the runner frees it after the current test. RefCounted instances are
|
||||
## accepted but ignored because they manage their own lifetime.
|
||||
func track(obj: Object) -> Object:
|
||||
if obj != null and not obj is RefCounted:
|
||||
_tracked_objects.append(obj)
|
||||
return obj
|
||||
|
||||
|
||||
## Free everything registered via track(). Called by the runner after each
|
||||
## test's teardown() and again after suite_teardown().
|
||||
func _free_tracked() -> void:
|
||||
for obj in _tracked_objects:
|
||||
if not is_instance_valid(obj) or (obj is Node and obj.is_queued_for_deletion()):
|
||||
continue
|
||||
if obj is Node:
|
||||
var parent := (obj as Node).get_parent()
|
||||
if parent != null:
|
||||
parent.remove_child(obj)
|
||||
obj.free()
|
||||
_tracked_objects.clear()
|
||||
|
||||
|
||||
# ----- assertion state (managed by McpTestRunner) -----
|
||||
|
||||
var _failed: bool = false
|
||||
@@ -38,6 +66,7 @@ var _message: String = ""
|
||||
var _assertion_count: int = 0
|
||||
var _skipped: bool = false
|
||||
var _skip_reason: String = ""
|
||||
var _expected_script_error_substrings: Array[String] = []
|
||||
|
||||
# ----- suite-level state (managed by McpTestRunner) -----
|
||||
|
||||
@@ -53,6 +82,7 @@ func _reset() -> void:
|
||||
_assertion_count = 0
|
||||
_skipped = false
|
||||
_skip_reason = ""
|
||||
_expected_script_error_substrings.clear()
|
||||
|
||||
|
||||
func _reset_suite_state() -> void:
|
||||
@@ -121,6 +151,29 @@ func skip_on_godot_lt(min_version: String, reason: String = "") -> bool:
|
||||
return false
|
||||
|
||||
|
||||
## Allow one captured SCRIPT ERROR whose text contains `substring`.
|
||||
## Use only for negative-path tests that intentionally compile or execute
|
||||
## invalid GDScript and assert on the resulting diagnostics.
|
||||
func expect_script_error_containing(substring: String) -> void:
|
||||
_expected_script_error_substrings.append(substring)
|
||||
|
||||
|
||||
func _unexpected_script_errors(captured: PackedStringArray) -> PackedStringArray:
|
||||
var unexpected := PackedStringArray()
|
||||
var remaining := _expected_script_error_substrings.duplicate()
|
||||
for error in captured:
|
||||
var matched_index := -1
|
||||
for i in range(remaining.size()):
|
||||
if error.find(remaining[i]) != -1:
|
||||
matched_index = i
|
||||
break
|
||||
if matched_index == -1:
|
||||
unexpected.append(error)
|
||||
else:
|
||||
remaining.remove_at(matched_index)
|
||||
return unexpected
|
||||
|
||||
|
||||
## Trigger an undo against whichever history (scene or global) holds the most
|
||||
## recent action. `EditorUndoRedoManager` in Godot 4.x doesn't expose `.undo()`
|
||||
## directly — you resolve the history's underlying UndoRedo and call it there.
|
||||
|
||||
Reference in New Issue
Block a user