Adding log.gd

This commit is contained in:
Dan Baker 2024-05-02 09:36:31 +01:00
parent eb32d6614e
commit 4522259397
547 changed files with 46844 additions and 0 deletions

View file

@ -0,0 +1,332 @@
# GdUnit generated TestSuite
class_name GdUnitSpyBuilderTest
extends GdUnitTestSuite
# TestSuite generated from
const __source = 'res://addons/gdUnit4/src/spy/GdUnitSpyBuilder.gd'
# helper to get function descriptor
func get_function_description(clazz_name :String, method_name :String) -> GdFunctionDescriptor:
var method_list :Array = ClassDB.class_get_method_list(clazz_name)
for method_descriptor in method_list:
if method_descriptor["name"] == method_name:
return GdFunctionDescriptor.extract_from(method_descriptor)
return null
func test_double__init() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void _init() virtual
var fd := get_function_description("Object", "_init")
var expected := [
'func _init() -> void:',
' super()',
' pass',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_typed_function_without_arg() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# String get_class() const
var fd := get_function_description("Object", "get_class")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func get_class() -> String:',
' var args :Array = ["get_class", ]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return ""',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("get_class"):',
' return super()',
' return ""',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_typed_function_with_args() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# bool is_connected(signal: String,Callable(target: Object,method: String)) const
var fd := get_function_description("Object", "is_connected")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func is_connected(signal_, callable_) -> bool:',
' var args :Array = ["is_connected", signal_, callable_]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return false',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("is_connected"):',
' return super(signal_, callable_)',
' return false',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_void_function_with_args() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void disconnect(signal: StringName, callable: Callable)
var fd := get_function_description("Object", "disconnect")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func disconnect(signal_, callable_) -> void:',
' var args :Array = ["disconnect", signal_, callable_]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("disconnect"):',
' super(signal_, callable_)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_void_function_without_args() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void free()
var fd := get_function_description("Object", "free")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func free() -> void:',
' var args :Array = ["free", ]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("free"):',
' super()',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_typed_function_with_args_and_varargs() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# Error emit_signal(signal: StringName, ...) vararg
var fd := get_function_description("Object", "emit_signal")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("int_as_enum_without_match")',
'@warning_ignore("int_as_enum_without_cast")',
'@warning_ignore("shadowed_variable")',
'func emit_signal(signal_, vararg0_="__null__", vararg1_="__null__", vararg2_="__null__", vararg3_="__null__", vararg4_="__null__", vararg5_="__null__", vararg6_="__null__", vararg7_="__null__", vararg8_="__null__", vararg9_="__null__") -> Error:',
' var varargs :Array = __filter_vargs([vararg0_, vararg1_, vararg2_, vararg3_, vararg4_, vararg5_, vararg6_, vararg7_, vararg8_, vararg9_])',
' var args :Array = ["emit_signal", signal_] + varargs',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return OK',
' else:',
' __save_function_interaction(args)',
'',
' return __call_func("emit_signal", [signal_] + varargs)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_void_function_only_varargs() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void bar(s...) vararg
var fd := GdFunctionDescriptor.new( "bar", 23, false, false, false, TYPE_NIL, "void", [], GdFunctionDescriptor._build_varargs(true))
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("shadowed_variable")',
'func bar(vararg0_="__null__", vararg1_="__null__", vararg2_="__null__", vararg3_="__null__", vararg4_="__null__", vararg5_="__null__", vararg6_="__null__", vararg7_="__null__", vararg8_="__null__", vararg9_="__null__") -> void:',
' var varargs :Array = __filter_vargs([vararg0_, vararg1_, vararg2_, vararg3_, vararg4_, vararg5_, vararg6_, vararg7_, vararg8_, vararg9_])',
' var args :Array = ["bar", ] + varargs',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return',
' else:',
' __save_function_interaction(args)',
'',
' __call_func("bar", [] + varargs)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_return_typed_function_only_varargs() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# String bar(s...) vararg
var fd := GdFunctionDescriptor.new( "bar", 23, false, false, false, TYPE_STRING, "String", [], GdFunctionDescriptor._build_varargs(true))
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("shadowed_variable")',
'func bar(vararg0_="__null__", vararg1_="__null__", vararg2_="__null__", vararg3_="__null__", vararg4_="__null__", vararg5_="__null__", vararg6_="__null__", vararg7_="__null__", vararg8_="__null__", vararg9_="__null__") -> String:',
' var varargs :Array = __filter_vargs([vararg0_, vararg1_, vararg2_, vararg3_, vararg4_, vararg5_, vararg6_, vararg7_, vararg8_, vararg9_])',
' var args :Array = ["bar", ] + varargs',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return ""',
' else:',
' __save_function_interaction(args)',
'',
' return __call_func("bar", [] + varargs)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_static_return_void_function_without_args() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void foo()
var fd := GdFunctionDescriptor.new( "foo", 23, false, true, false, TYPE_NIL, "", [])
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("shadowed_variable")',
'static func foo() -> void:',
' var args :Array = ["foo", ]',
'',
' if __instance().__is_verify_interactions():',
' __instance().__verify_interactions(args)',
' return',
' else:',
' __instance().__save_function_interaction(args)',
'',
' if __instance().__do_call_real_func("foo"):',
' super()',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_static_return_void_function_with_args() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
var fd := GdFunctionDescriptor.new( "foo", 23, false, true, false, TYPE_NIL, "", [
GdFunctionArgument.new("arg1", TYPE_BOOL),
GdFunctionArgument.new("arg2", TYPE_STRING, '"default"')
])
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("shadowed_variable")',
'static func foo(arg1, arg2="default") -> void:',
' var args :Array = ["foo", arg1, arg2]',
'',
' if __instance().__is_verify_interactions():',
' __instance().__verify_interactions(args)',
' return',
' else:',
' __instance().__save_function_interaction(args)',
'',
' if __instance().__do_call_real_func("foo"):',
' super(arg1, arg2)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_static_script_function_with_args_return_bool() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
var fd := GdFunctionDescriptor.new( "foo", 23, false, true, false, TYPE_BOOL, "", [
GdFunctionArgument.new("arg1", TYPE_BOOL),
GdFunctionArgument.new("arg2", TYPE_STRING, '"default"')
])
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("shadowed_variable")',
'static func foo(arg1, arg2="default") -> bool:',
' var args :Array = ["foo", arg1, arg2]',
'',
' if __instance().__is_verify_interactions():',
' __instance().__verify_interactions(args)',
' return false',
' else:',
' __instance().__save_function_interaction(args)',
'',
' if __instance().__do_call_real_func("foo"):',
' return super(arg1, arg2)',
' return false',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_virtual_return_void_function_with_arg() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void _input(event: InputEvent) virtual
var fd := get_function_description("Node", "_input")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func _input(event_) -> void:',
' var args :Array = ["_input", event_]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("_input"):',
' super(event_)',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
func test_double_virtual_return_void_function_without_arg() -> void:
var doubler := GdUnitSpyFunctionDoubler.new(false)
# void _ready() virtual
var fd := get_function_description("Node", "_ready")
var expected := [
'@warning_ignore("untyped_declaration")' if Engine.get_version_info().hex >= 0x40200 else '',
'@warning_ignore("native_method_override")',
'@warning_ignore("shadowed_variable")',
'func _ready() -> void:',
' var args :Array = ["_ready", ]',
'',
' if __is_verify_interactions():',
' __verify_interactions(args)',
' return',
' else:',
' __save_function_interaction(args)',
'',
' if __do_call_real_func("_ready"):',
' super()',
'',
'']
assert_array(doubler.double(fd)).contains_exactly(expected)
class NodeWithOutVirtualFunc extends Node:
func _ready():
pass
#func _input(event :InputEvent) -> void:
func test_spy_on_script_respect_virtual_functions():
var do_spy = auto_free(GdUnitSpyBuilder.spy_on_script(auto_free(NodeWithOutVirtualFunc.new()), [], true).new())
assert_that(do_spy.has_method("_ready")).is_true()
assert_that(do_spy.has_method("_input")).is_false()

View file

@ -0,0 +1,621 @@
class_name GdUnitSpyTest
extends GdUnitTestSuite
func test_spy_instance_id_is_unique():
var m1 = spy(RefCounted.new())
var m2 = spy(RefCounted.new())
# test the internal instance id is unique
assert_that(m1.__instance_id()).is_not_equal(m2.__instance_id())
assert_object(m1).is_not_same(m2)
func test_cant_spy_is_not_a_instance():
# returns null because spy needs an 'real' instance to by spy checked
var spy_node = spy(Node)
assert_object(spy_node).is_null()
func test_spy_on_Node():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# verify we have no interactions currently checked this instance
verify_no_interactions(spy_node)
assert_object(spy_node)\
.is_not_null()\
.is_instanceof(Node)\
.is_not_same(instance)
# call first time
spy_node.set_process(false)
# verify is called one times
verify(spy_node).set_process(false)
# just double check that verify has no affect to the counter
verify(spy_node).set_process(false)
# call a scond time
spy_node.set_process(false)
# verify is called two times
verify(spy_node, 2).set_process(false)
verify(spy_node, 2).set_process(false)
func test_spy_source_with_class_name_by_resource_path() -> void:
var instance = auto_free(load('res://addons/gdUnit4/test/mocker/resources/GD-256/world.gd').new())
var m = spy(instance)
var head :String = m.get_script().source_code.substr(0, 200)
assert_str(head)\
.contains("class_name DoubledMunderwoodPathingWorld")\
.contains("extends 'res://addons/gdUnit4/test/mocker/resources/GD-256/world.gd'")
func test_spy_source_with_class_name_by_class() -> void:
var m = spy(auto_free(Munderwood_Pathing_World.new()))
var head :String = m.get_script().source_code.substr(0, 200)
assert_str(head)\
.contains("class_name DoubledMunderwoodPathingWorld")\
.contains("extends 'res://addons/gdUnit4/test/mocker/resources/GD-256/world.gd'")
func test_spy_extends_godot_class() -> void:
var m = spy(auto_free(World3D.new()))
var head :String = m.get_script().source_code.substr(0, 200)
assert_str(head)\
.contains("class_name DoubledWorld")\
.contains("extends World3D")
func test_spy_on_custom_class():
var instance :AdvancedTestClass = auto_free(AdvancedTestClass.new())
var spy_instance = spy(instance)
# verify we have currently no interactions
verify_no_interactions(spy_instance)
assert_object(spy_instance)\
.is_not_null()\
.is_instanceof(AdvancedTestClass)\
.is_not_same(instance)
spy_instance.setup_local_to_scene()
verify(spy_instance, 1).setup_local_to_scene()
# call first time script func with different arguments
spy_instance.get_area("test_a")
spy_instance.get_area("test_b")
spy_instance.get_area("test_c")
# verify is each called only one time for different arguments
verify(spy_instance, 1).get_area("test_a")
verify(spy_instance, 1).get_area("test_b")
verify(spy_instance, 1).get_area("test_c")
# an second call with arg "test_c"
spy_instance.get_area("test_c")
verify(spy_instance, 1).get_area("test_a")
verify(spy_instance, 1).get_area("test_b")
verify(spy_instance, 2).get_area("test_c")
# verify if a not used argument not counted
verify(spy_instance, 0).get_area("test_no")
# GD-291 https://github.com/MikeSchulze/gdUnit4/issues/291
func test_spy_class_with_custom_formattings() -> void:
var resource = load("res://addons/gdUnit4/test/mocker/resources/ClassWithCustomFormattings.gd")
var do_spy = spy(auto_free(resource.new("test")))
do_spy.a1("set_name", "", true)
verify(do_spy, 1).a1("set_name", "", true)
verify_no_more_interactions(do_spy)
assert_failure(func(): verify_no_interactions(do_spy))\
.is_failed() \
.has_line(112)
func test_spy_copied_class_members():
var instance = auto_free(load("res://addons/gdUnit4/test/mocker/resources/TestPersion.gd").new("user-x", "street", 56616))
assert_that(instance._name).is_equal("user-x")
assert_that(instance._value).is_equal(1024)
assert_that(instance._address._street).is_equal("street")
assert_that(instance._address._code).is_equal(56616)
# spy it
var spy_instance = spy(instance)
reset(spy_instance)
# verify members are inital copied
assert_that(spy_instance._name).is_equal("user-x")
assert_that(spy_instance._value).is_equal(1024)
assert_that(spy_instance._address._street).is_equal("street")
assert_that(spy_instance._address._code).is_equal(56616)
spy_instance._value = 2048
assert_that(instance._value).is_equal(1024)
assert_that(spy_instance._value).is_equal(2048)
func test_spy_copied_class_members_on_node():
var node :Node = auto_free(Node.new())
# checked a fresh node the name is empty and results into a error when copied at spy
# E 0:00:01.518 set_name: Condition "name == """ is true.
# C++ Source> scene/main/node.cpp:934 @ set_name()
# we set a placeholder instead
assert_that(spy(node).name).is_equal("<empty>")
node.set_name("foo")
assert_that(spy(node).name).is_equal("foo")
func test_spy_on_inner_class():
var instance :AdvancedTestClass.AtmosphereData = auto_free(AdvancedTestClass.AtmosphereData.new())
var spy_instance :AdvancedTestClass.AtmosphereData = spy(instance)
# verify we have currently no interactions
verify_no_interactions(spy_instance)
assert_object(spy_instance)\
.is_not_null()\
.is_instanceof(AdvancedTestClass.AtmosphereData)\
.is_not_same(instance)
spy_instance.set_data(AdvancedTestClass.AtmosphereData.SMOKY, 1.2)
spy_instance.set_data(AdvancedTestClass.AtmosphereData.SMOKY, 1.3)
verify(spy_instance, 1).set_data(AdvancedTestClass.AtmosphereData.SMOKY, 1.2)
verify(spy_instance, 1).set_data(AdvancedTestClass.AtmosphereData.SMOKY, 1.3)
func test_spy_on_singleton():
await assert_error(func () -> void:
var spy_node_ = spy(Input)
assert_object(spy_node_).is_null()
await await_idle_frame()).is_push_error("Spy on a Singleton is not allowed! 'Input'")
func test_example_verify():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# verify we have no interactions currently checked this instance
verify_no_interactions(spy_node)
# call with different arguments
spy_node.set_process(false) # 1 times
spy_node.set_process(true) # 1 times
spy_node.set_process(true) # 2 times
# verify how often we called the function with different argument
verify(spy_node, 2).set_process(true) # in sum two times with true
verify(spy_node, 1).set_process(false)# in sum one time with false
# verify total sum by using an argument matcher
verify(spy_node, 3).set_process(any_bool())
func test_verify_fail():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# interact two time
spy_node.set_process(true) # 1 times
spy_node.set_process(true) # 2 times
# verify we interacts two times
verify(spy_node, 2).set_process(true)
# verify should fail because we interacts two times and not one
var expected_error := """
Expecting interaction on:
'set_process(true :bool)' 1 time's
But found interactions on:
'set_process(true :bool)' 2 time's""" \
.dedent().trim_prefix("\n")
assert_failure(func(): verify(spy_node, 1).set_process(true)) \
.is_failed() \
.has_line(214) \
.has_message(expected_error)
func test_verify_func_interaction_wiht_PoolStringArray():
var spy_instance :ClassWithPoolStringArrayFunc = spy(ClassWithPoolStringArrayFunc.new())
spy_instance.set_values(PackedStringArray())
verify(spy_instance).set_values(PackedStringArray())
verify_no_more_interactions(spy_instance)
func test_verify_func_interaction_wiht_PackedStringArray_fail():
var spy_instance :ClassWithPoolStringArrayFunc = spy(ClassWithPoolStringArrayFunc.new())
spy_instance.set_values(PackedStringArray())
# try to verify with default array type instead of PackedStringArray type
var expected_error := """
Expecting interaction on:
'set_values([] :Array)' 1 time's
But found interactions on:
'set_values([] :PackedStringArray)' 1 time's""" \
.dedent().trim_prefix("\n")
assert_failure(func(): verify(spy_instance, 1).set_values([])) \
.is_failed() \
.has_line(241) \
.has_message(expected_error)
reset(spy_instance)
# try again with called two times and different args
spy_instance.set_values(PackedStringArray())
spy_instance.set_values(PackedStringArray(["a", "b"]))
spy_instance.set_values([1, 2])
expected_error = """
Expecting interaction on:
'set_values([] :Array)' 1 time's
But found interactions on:
'set_values([] :PackedStringArray)' 1 time's
'set_values(["a", "b"] :PackedStringArray)' 1 time's
'set_values([1, 2] :Array)' 1 time's""" \
.dedent().trim_prefix("\n")
assert_failure(func(): verify(spy_instance, 1).set_values([])) \
.is_failed() \
.has_line(259) \
.has_message(expected_error)
func test_reset():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# call with different arguments
spy_node.set_process(false) # 1 times
spy_node.set_process(true) # 1 times
spy_node.set_process(true) # 2 times
verify(spy_node, 2).set_process(true)
verify(spy_node, 1).set_process(false)
# now reset the spy
reset(spy_node)
# verify all counters have been reset
verify_no_interactions(spy_node)
func test_verify_no_interactions():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# verify we have no interactions checked this mock
verify_no_interactions(spy_node)
func test_verify_no_interactions_fails():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
# interact
spy_node.set_process(false) # 1 times
spy_node.set_process(true) # 1 times
spy_node.set_process(true) # 2 times
var expected_error ="""
Expecting no more interactions!
But found interactions on:
'set_process(false :bool)' 1 time's
'set_process(true :bool)' 2 time's""" \
.dedent().trim_prefix("\n")
# it should fail because we have interactions
assert_failure(func(): verify_no_interactions(spy_node)) \
.is_failed() \
.has_line(307) \
.has_message(expected_error)
func test_verify_no_more_interactions():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
spy_node.is_ancestor_of(instance)
spy_node.set_process(false)
spy_node.set_process(true)
spy_node.set_process(true)
# verify for called functions
verify(spy_node, 1).is_ancestor_of(instance)
verify(spy_node, 2).set_process(true)
verify(spy_node, 1).set_process(false)
# There should be no more interactions checked this mock
verify_no_more_interactions(spy_node)
func test_verify_no_more_interactions_but_has():
var instance :Node = auto_free(Node.new())
var spy_node = spy(instance)
spy_node.is_ancestor_of(instance)
spy_node.set_process(false)
spy_node.set_process(true)
spy_node.set_process(true)
# now we simulate extra calls that we are not explicit verify
spy_node.is_inside_tree()
spy_node.is_inside_tree()
# a function with default agrs
spy_node.find_child("mask")
# same function again with custom agrs
spy_node.find_child("mask", false, false)
# verify 'all' exclusive the 'extra calls' functions
verify(spy_node, 1).is_ancestor_of(instance)
verify(spy_node, 2).set_process(true)
verify(spy_node, 1).set_process(false)
# now use 'verify_no_more_interactions' to check we have no more interactions checked this mock
# but should fail with a collecion of all not validated interactions
var expected_error ="""
Expecting no more interactions!
But found interactions on:
'is_inside_tree()' 2 time's
'find_child(mask :String, true :bool, true :bool)' 1 time's
'find_child(mask :String, false :bool, false :bool)' 1 time's""" \
.dedent().trim_prefix("\n")
assert_failure(func(): verify_no_more_interactions(spy_node)) \
.is_failed() \
.has_line(362) \
.has_message(expected_error)
class ClassWithStaticFunctions:
static func foo() -> void:
pass
static func bar():
pass
func test_create_spy_static_func_untyped():
var instance = spy(ClassWithStaticFunctions.new())
assert_object(instance).is_not_null()
func test_spy_snake_case_named_class_by_resource_path():
var instance_a = load("res://addons/gdUnit4/test/mocker/resources/snake_case.gd").new()
var spy_a = spy(instance_a)
assert_object(spy_a).is_not_null()
spy_a.custom_func()
verify(spy_a).custom_func()
verify_no_more_interactions(spy_a)
var instance_b = load("res://addons/gdUnit4/test/mocker/resources/snake_case_class_name.gd").new()
var spy_b = spy(instance_b)
assert_object(spy_b).is_not_null()
spy_b.custom_func()
verify(spy_b).custom_func()
verify_no_more_interactions(spy_b)
func test_spy_snake_case_named_class_by_class():
var do_spy = spy(snake_case_class_name.new())
assert_object(do_spy).is_not_null()
do_spy.custom_func()
verify(do_spy).custom_func()
verify_no_more_interactions(do_spy)
# try checked Godot class
var spy_tcp_server = spy(TCPServer.new())
assert_object(spy_tcp_server).is_not_null()
spy_tcp_server.is_listening()
spy_tcp_server.is_connection_available()
verify(spy_tcp_server).is_listening()
verify(spy_tcp_server).is_connection_available()
verify_no_more_interactions(spy_tcp_server)
const Issue = preload("res://addons/gdUnit4/test/resources/issues/gd-166/issue.gd")
const Type = preload("res://addons/gdUnit4/test/resources/issues/gd-166/types.gd")
func test_spy_preload_class_GD_166() -> void:
var instance = auto_free(Issue.new())
var spy_instance = spy(instance)
spy_instance.type = Type.FOO
verify(spy_instance, 1)._set_type_name(Type.FOO)
assert_int(spy_instance.type).is_equal(Type.FOO)
assert_str(spy_instance.type_name).is_equal("FOO")
var _test_signal_args := Array()
func _emit_ready(a, b, c = null):
_test_signal_args = [a, b, c]
# https://github.com/MikeSchulze/gdUnit4/issues/38
func test_spy_Node_use_real_func_vararg():
# setup
var instance := Node.new()
instance.connect("ready", _emit_ready)
assert_that(_test_signal_args).is_empty()
var spy_node = spy(auto_free(instance))
assert_that(spy_node).is_not_null()
# test emit it
spy_node.emit_signal("ready", "aa", "bb", "cc")
# verify is emitted
verify(spy_node).emit_signal("ready", "aa", "bb", "cc")
await get_tree().process_frame
assert_that(_test_signal_args).is_equal(["aa", "bb", "cc"])
# test emit it
spy_node.emit_signal("ready", "aa", "xxx")
# verify is emitted
verify(spy_node).emit_signal("ready", "aa", "xxx")
await get_tree().process_frame
assert_that(_test_signal_args).is_equal(["aa", "xxx", null])
class ClassWithSignal:
signal test_signal_a
signal test_signal_b
func foo(arg :int) -> void:
if arg == 0:
emit_signal("test_signal_a", "aa")
else:
emit_signal("test_signal_b", "bb", true)
func bar(arg :int) -> bool:
if arg == 0:
emit_signal("test_signal_a", "aa")
else:
emit_signal("test_signal_b", "bb", true)
return true
# https://github.com/MikeSchulze/gdUnit4/issues/14
func _test_spy_verify_emit_signal():
var spy_instance = spy(ClassWithSignal.new())
assert_that(spy_instance).is_not_null()
spy_instance.foo(0)
verify(spy_instance, 1).emit_signal("test_signal_a", "aa")
verify(spy_instance, 0).emit_signal("test_signal_b", "bb", true)
reset(spy_instance)
spy_instance.foo(1)
verify(spy_instance, 0).emit_signal("test_signal_a", "aa")
verify(spy_instance, 1).emit_signal("test_signal_b", "bb", true)
reset(spy_instance)
spy_instance.bar(0)
verify(spy_instance, 1).emit_signal("test_signal_a", "aa")
verify(spy_instance, 0).emit_signal("test_signal_b", "bb", true)
reset(spy_instance)
spy_instance.bar(1)
verify(spy_instance, 0).emit_signal("test_signal_a", "aa")
verify(spy_instance, 1).emit_signal("test_signal_b", "bb", true)
func test_spy_func_with_default_build_in_type():
var spy_instance :ClassWithDefaultBuildIntTypes = spy(ClassWithDefaultBuildIntTypes.new())
assert_object(spy_instance).is_not_null()
# call with default arg
spy_instance.foo("abc")
spy_instance.bar("def")
verify(spy_instance).foo("abc", Color.RED)
verify(spy_instance).bar("def", Vector3.FORWARD, AABB())
verify_no_more_interactions(spy_instance)
# call with custom args
spy_instance.foo("abc", Color.BLUE)
spy_instance.bar("def", Vector3.DOWN, AABB(Vector3.ONE, Vector3.ZERO))
verify(spy_instance).foo("abc", Color.BLUE)
verify(spy_instance).bar("def", Vector3.DOWN, AABB(Vector3.ONE, Vector3.ZERO))
verify_no_more_interactions(spy_instance)
func test_spy_scene_by_resource_path():
var spy_scene = spy("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
assert_object(spy_scene)\
.is_not_null()\
.is_not_instanceof(PackedScene)\
.is_instanceof(Control)
assert_str(spy_scene.get_script().resource_name).is_equal("SpyTestScene.gd")
# check is spyed scene registered for auto freeing
assert_bool(GdUnitMemoryObserver.is_marked_auto_free(spy_scene)).is_true()
func test_spy_on_PackedScene():
var resource := load("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
var original_script = resource.get_script()
assert_object(resource).is_instanceof(PackedScene)
var spy_scene = spy(resource)
assert_object(spy_scene)\
.is_not_null()\
.is_not_instanceof(PackedScene)\
.is_not_same(resource)
assert_object(spy_scene.get_script())\
.is_not_null()\
.is_instanceof(GDScript)\
.is_not_same(original_script)
assert_str(spy_scene.get_script().resource_name).is_equal("SpyTestScene.gd")
# check is spyed scene registered for auto freeing
assert_bool(GdUnitMemoryObserver.is_marked_auto_free(spy_scene)).is_true()
func test_spy_scene_by_instance():
var resource := load("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
var instance :Control = resource.instantiate()
var original_script = instance.get_script()
var spy_scene = spy(instance)
assert_object(spy_scene)\
.is_not_null()\
.is_same(instance)\
.is_instanceof(Control)
assert_object(spy_scene.get_script())\
.is_not_null()\
.is_instanceof(GDScript)\
.is_not_same(original_script)
assert_str(spy_scene.get_script().resource_name).is_equal("SpyTestScene.gd")
# check is mocked scene registered for auto freeing
assert_bool(GdUnitMemoryObserver.is_marked_auto_free(spy_scene)).is_true()
func test_spy_scene_by_path_fail_has_no_script_attached():
var resource := load("res://addons/gdUnit4/test/mocker/resources/scenes/TestSceneWithoutScript.tscn")
var instance :Control = auto_free(resource.instantiate())
# has to fail and return null
var spy_scene = spy(instance)
assert_object(spy_scene).is_null()
func test_spy_scene_initalize():
var spy_scene = spy("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
assert_object(spy_scene).is_not_null()
# Add as child to a scene tree to trigger _ready to initalize all variables
add_child(spy_scene)
# ensure _ready is recoreded and onyl once called
verify(spy_scene, 1)._ready()
verify(spy_scene, 1).only_one_time_call()
assert_object(spy_scene._box1).is_not_null()
assert_object(spy_scene._box2).is_not_null()
assert_object(spy_scene._box3).is_not_null()
# check signals are connected
assert_bool(spy_scene.is_connected("panel_color_change",Callable(spy_scene,"_on_panel_color_changed")))
# check exports
assert_str(spy_scene._initial_color.to_html()).is_equal(Color.RED.to_html())
class CustomNode extends Node:
func _ready():
# we call this function to verify the _ready is only once called
# this is need to verify `add_child` is calling the original implementation only once
only_one_time_call()
func only_one_time_call() -> void:
pass
func test_spy_ready_called_once():
var spy_node = spy(auto_free(CustomNode.new()))
# Add as child to a scene tree to trigger _ready to initalize all variables
add_child(spy_node)
# ensure _ready is recoreded and onyl once called
verify(spy_node, 1)._ready()
verify(spy_node, 1).only_one_time_call()