-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add doubled parent #660
Comments
In the other case, we cannot stub mouse position getters:
|
I am pretty sure that this has to do with optimizations that Godot is making in the background, which is making stubbing more and more difficult. Godot will call some methods directly, without going through inheritance. This is why they introduced the "Native Method Override" warning, and why you must use When you call the method directly from a test it appears that it honors the inheritance and calls the doubled method. When the methods are called from within I tried to confuse it enough that it might call the doubled method but that didn't work. Even in the code below, the doubled methods are not called: #my_class
...
var me = null
func _process(_delta):
something_pos = me.get_local_mouse_position()
me.get_index()
...
# test script
_my_class = double(MyClass, DOUBLE_STRATEGY.INCLUDE_NATIVE).new()
_my_class.me = _my_class
I also tried this with a method call WorkaroundsIn this particular example, the only thing I can think to do is to wrap func handle_mouse_position(mpos):
# do stuff with the mouse position here
func _process(_delta):
handle_mouse_position(get_local_mouse_position()) See Also |
Oh... I see. Thank you. How's an idea like this:
Sample code for replace: extends Node
const PATTERN = "(?<=[^\\p{ID_Continue}])%s(?=[^\\p{ID_Continue}])"
const REPLACEMENT = "__$0"
const SCRIPT = '''
func _ready():
var value =native_method()
var value = native_method()
native_method(native_method())
native_method(native_method)
native_method(
native_method(),native_method()
)
native_method ()
native_method \
()
not_native_method()
native_method_hack()
'''
const METHOD_NAME = "native_method"
func _ready():
var regex = RegEx.new()
regex.compile(PATTERN % METHOD_NAME)
var new_script = regex.sub(SCRIPT, REPLACEMENT, true)
print(new_script) |
I've been thinking about this for a bit, but I don't think it will work. If you are asking to replace internal calls to native methods with a wrapper method then GUT can't do this as it currently works. When GUT creates a double, it doesn't include any of the original source, it only extends and overrides methods. Since it doesn't have any code from the body of methods, there aren't any calls to replace with the regex. If we added an extra class between the original and the double then maybe this could work. You'd have to apply the regex and then generate all native wrappers, then create a double of the "Regexed" class. If you did this with It seems this would allow stubbing/spying for any internal calls to native methods, but external calls will still be unreliable. I was excited about this idea's potential, but it feels overly complicated and likely won't solve enough of the issues with stubbing/spying on native methods. If I didn't understand your original idea, or you have other ideas let me know. |
My text has misled you a bit. In my regex idea, Let
# my_class.gd
extends Node
func _process(_delta):
get_index()
# doubled_my_class.gd
extends "path/to/replaced_my_class.gd"
...
func _process(p__delta=__gutdbl.default_val("_process",0)):
__gutdbl.spy_on('_process', [p__delta])
if(__gutdbl.is_stubbed_to_call_super('_process', [p__delta])):
return await super(p__delta)
else:
return await __gutdbl.handle_other_stubs('_process', [p__delta])
... and # replaced_my_class.gd
extends Node
...
func _process(_delta):
__get_index()
...
func __get_index(p_include_internal=__gutdbl.default_val("get_index",0)):
__gutdbl.spy_on('get_index', [p_include_internal])
if(__gutdbl.is_stubbed_to_call_super('get_index', [p_include_internal])):
return await super.get_index(p_include_internal)
else:
return await __gutdbl.handle_other_stubs('get_index', [p_include_internal])
... Therefore, the result class extends like: graph LR;
A --> B --> C
A[Doubled MyClass]
B[Replaced MyClass]
C[MyClass parent]
|
It's good to unify # replaced_my_class.gd
extends Node
...
func ___process(_delta):
__get_index()
...
func _process(p__delta=__gutdbl.default_val("_process",0)):
__gutdbl.spy_on('_process', [p__delta])
if(__gutdbl.is_stubbed_to_call_super('_process', [p__delta])):
return await ___process(p__delta)
else:
return await __gutdbl.handle_other_stubs('_process', [p__delta])
...
func __get_index(p_include_internal=__gutdbl.default_val("get_index",0)):
__gutdbl.spy_on('get_index', [p_include_internal])
if(__gutdbl.is_stubbed_to_call_super('get_index', [p_include_internal])):
return await super.get_index(p_include_internal)
else:
return await __gutdbl.handle_other_stubs('get_index', [p_include_internal])
... graph LR;
A --> B
A[Replaced MyClass]
B[MyClass parent]
|
Ok. I think this is what I was saying in the 2nd paragraph ("If we added an extra class between the original and the double...."). I like the idea, but I'm not sure if adding it is worth the trouble, given all the scenarios where this will not help. This would go low on my priority list, but I would entertain PRs. |
Versions
Godot: v4.2.2.stable.official [15073afe3]
The Feature
double(MyClass)
makes a class that extends like:Background
Current
double(MyClass)
seems to make a class that extends like:This cannot spy calling super methods from inside
MyClass
script.It is because the methods in
MyClass
context refer to the actual parent's methods.For example:
This feature may be out of the testing philosophy because tests can be made regarding the target implementation.
However, I want to spy on native super methods and request this feature.
The text was updated successfully, but these errors were encountered: