Open encrest opened 6 days ago
TL;DR. If you remove the static typing for audio_player
the test will pass. It has to do with native method overrides and the engine not calling overrides generated by the double. This issue has some info: https://github.com/godotengine/godot/issues/55024
I think this is a limitation with Godot and is an example of why they introduced the "Native Method Override" warning. In the following test, assert_called
fails, but the assert_eq
passes. This means set_position
was called and it worked but it shouldn't have because dbl_node2d
is not a partial_double
and set_position
was not stubbed. So I'm guessing the Engine called the "native method" set_position
directly without using the method in the double. It seems that when the variable is not statically typed the engine cannot make this optimization and ends up calling the double's method.
func test_double_node2d():
var dbl_node2d : Node2D = double(Node2D).new()
dbl_node2d.set_position(Vector2(100, 100))
assert_called(dbl_node2d, 'set_position')
assert_eq(dbl_node2d.position, Vector2(100, 100))
In another example, I created a Node2D subclass and the methods in the class are tracked as being called, but set_position
is not. If you remove the static typing then set_position
is tracked but the assert_eq
fails because set_position
was not stubbed.
class ThisThing:
extends Node2D
func say_something():
print('something')
func test_double_this_guy():
register_inner_classes(get_script())
var dbl_this_thing : ThisThing = partial_double(ThisThing, DOUBLE_STRATEGY.INCLUDE_NATIVE).new()
dbl_this_thing.set_position(Vector2(100, 100))
dbl_this_thing.say_something()
assert_called(dbl_this_thing, 'set_position')
assert_called(dbl_this_thing, 'say_something')
assert_eq(dbl_this_thing.position, Vector2(100, 100))
This should be documented in GUT. I don't think it ever occurred to me to statically type double vars. If you are doing it to avoid warnings, the next release of GUT (currently in main
) has some changes that will turn off warnings when loading and running tests so at least your output is less noisy...though you may still have some squiggly lines in the editor.
Thanks so much for the quick response! Removing the static type declaration on the double fixed the test for me! For posterity, I swapped in this line for the audio_player declaration: var audio_player = double(AudioStreamPlayer3D, DOUBLE_STRATEGY.INCLUDE_NATIVE).new()
In my actual game test, I also had to remove the static type declaration on the class property I was assigning the double to as well.
Reopening until documentation has been added and because having to change the thing using it is ugly.
I'm not sure if there will be any other way to handle that, but I'd like to explore it a bit. It should at least be included in the documentation.
Versions
(list all versions where you have replicated the bug)
The Bug
assert_called and assert_called_times appear to be ignoring calls to a doubled AudioStreamPlayer3D's methods, and will fail in the below minimum reproducible example with the following output. I also tried without the DOUBLE_STRATEGY.INCLUDE_NATIVE param and saw the same result, and I see the same effect with other methods like "set_volume_db" and "set_pitch_scale".
I've gotten other doubles to work as I would expect such as a partial_double(Node3D) and a double of one of my own custom gdscript classes, so I'm not sure what I could've done wrong/differently here with AudioStreamPlayer3D.
Thanks in advance for any pointers!
===================================
res://scripts/tests/unit/test_gut.gd
at line 7
---- Totals ---- Scripts 1 Tests 1 Passing none Failing 1 Asserts 1 Time 2.127s
[Orphans]: 1 new orphan in total. Note: This count does not include GUT objects that will be freed upon exit. It also does not include any orphans created by global scripts loaded before tests were ran. Total orphans = 2
Ran Scripts matching "test_gut.gd" Ran Tests matching "test_double_updates_count" ---- 1 failing tests ----
Steps To Reproduce
Minimum reproducible example code: