### Setup and Teardown Methods in GUT Source: https://gut.readthedocs.io/en/latest/Quick-Start.html This GDScript example illustrates the use of setup and teardown methods within a GUT test class. It shows `before_all`, `before_each`, `after_each`, and `after_all` methods, along with example tests. ```gdscript extends GutTest func before_all(): gut.p("Runs once before all tests") func before_each(): gut.p("Runs before each test.") func after_each(): gut.p("Runs after each test.") func after_all(): gut.p("Runs once after all tests") func test_assert_eq_number_not_equal(): assert_eq(1, 2, "Should fail. 1 != 2") func test_assert_eq_number_equal(): assert_eq('asdf', 'asdf', "Should pass") ``` -------------------------------- ### Implement Test Lifecycle Methods in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Shows how to define setup and teardown methods (before/after all/each) to manage test state and environment, alongside standard test functions. ```gdscript extends GutTest func before_all(): gut.p("Runs once before all tests") func before_each(): gut.p("Runs before each test.") func after_each(): gut.p("Runs after each test.") func after_all(): gut.p("Runs once after all tests") func test_assert_eq_number_not_equal(): assert_eq(1, 2, "Should fail. 1 != 2") func test_assert_eq_number_equal(): assert_eq('asdf', 'asdf', "Should pass") ``` -------------------------------- ### Create Basic Unit Tests in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Demonstrates the basic structure of a GUT test script by extending GutTest and using assertion methods to validate expected outcomes. ```gdscript extends GutTest func test_passes(): # this test will pass because 1 does equal 1 assert_eq(1, 1) func test_fails(): # this test will fail because those strings are not equal assert_eq('hello', 'goodbye') ``` -------------------------------- ### Implementing Parameterized Tests Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Explains how to execute the same test logic multiple times with different input values. Supports both simple arrays and named parameters for better readability. ```gdscript var test_params = [[1, 2, 3], [4, 5, 6]] func test_with_parameters(p=use_parameters(test_params)): assert_eq(p[0], p[2] - p[1]) var named_params = ParameterFactory.named_parameters(['a', 'b'], [[1, 2], ['one', 'two']]) func test_with_named_params(p=use_parameters(named_params)): assert_ne(p.a, p.b) ``` -------------------------------- ### Create and Stub Test Doubles in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Illustrates how to create doubles for classes and scenes, and how to configure stubs to return specific values or execute custom logic during tests. ```gdscript var Foo = load('res://foo.gd') var MyScene = load('res://my_scene.tscn') var double_foo = double(Foo).new() var double_scene = double(MyScene).instantiate() # Stubbing examples stub(double_foo.bar).to_return(42) stub(double_foo, "something").to_call_super() stub(double_foo.other_thing).to_return(77).when_passed(1, 2, 'c') stub(double_foo.other_thing.bind(4, 5, 'z')).to_do_nothing() ``` -------------------------------- ### Implement Global Test Setup using GutHookScript Source: https://gut.readthedocs.io/en/latest/_sources/Global-Lifecycle-Hooks.md.txt Demonstrates how to extend GutHookScript to connect to GUT signals. This example specifically connects to the start_test signal to execute custom logic before every test method. ```GDScript extends GutHookScript func run(): gut.start_test.connect(_on_test_started) func _on_test_started(test_name): # setup logic run before every test in every test script goes here ``` -------------------------------- ### Connecting to GUT Start Test Signal Source: https://gut.readthedocs.io/en/latest/Global-Lifecycle-Hooks.html An example of a Pre-Run Hook script in GDScript that connects a custom function to the `start_test` signal. This allows for executing setup logic before every test in every test script. ```gdscript extends GutHookScript func run(): gut.start_test.connect(_on_test_started) func _on_test_started(test_name): # setup logic run before every test in every test script goes here pass ``` -------------------------------- ### Creating and Stubbing Partial Doubles Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Shows how to create partial doubles that retain original functionality while allowing specific methods to be stubbed or spied upon. Useful for isolating specific logic within existing classes. ```gdscript var double_bar = partial_double(Bar).instance() stub(double_bar.foo).to_do_nothing() stub(double_bar.something).to_return(27).when_passed(32) assert_called(double_bar, 'other_thing') ``` -------------------------------- ### Full Example of Singleton Injection and Stubbing Source: https://gut.readthedocs.io/en/latest/_sources/Doubling-Singletons.md.txt A complete example showing a class that uses the Time singleton and a corresponding test suite that injects a double to verify behavior, including handling of enums and method stubbing. ```gdscript class_name UsesTime var t := Time var _start_time = -1 func start(): _start_time = t.get_ticks_msec() func end(): var monday_extra = 0 if(t.get_date_dict_from_system().weekday == t.WEEKDAY_MONDAY): monday_extra = 10 return t.get_ticks_msec() - _start_time + monday_extra # Test implementation extends GutTest func test_calling_end_returns_elapsed_time_using_msecs(): var dbl_time = partial_double_singleton(Time).new() var inst = UsesTime.new() inst.t = dbl_time stub(dbl_time.get_ticks_msec).to_return(0) inst.start() stub(dbl_time.get_ticks_msec).to_return(10) assert_eq(inst.end(), 10) ``` -------------------------------- ### Full Example: Testing Classes with Time Dependency Source: https://gut.readthedocs.io/en/latest/Doubling-Singletons.html A complete example showing a class that depends on the Time singleton and a corresponding test suite that injects a double to verify logic. ```GDScript class_name UsesTime var t := Time var _start_time = -1 func start(): _start_time = t.get_ticks_msec() func end(): var monday_extra = 0 if(t.get_date_dict_from_system().weekday == t.WEEKDAY_MONDAY): monday_extra = 10 return t.get_ticks_msec() - _start_time + monday_extra # Test Suite extends GutTest func test_calling_end_returns_elapsed_time_using_msecs(): var dbl_time = partial_double_singleton(Time).new() var inst = UsesTime.new() inst.t = dbl_time stub(dbl_time.get_ticks_msec).to_return(0) inst.start() stub(dbl_time.get_ticks_msec).to_return(10) assert_eq(inst.end(), 10) ``` -------------------------------- ### Asserting and Inspecting Method Calls in GUT Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Demonstrates how to verify that methods were called with specific parameters on test doubles. Uses assertion helpers to inspect call history and retrieve parameter arrays. ```gdscript assert_called(double_foo, 'other_thing', [1, 2, 'c']) var called_with_last = get_call_parameters(double_foo, 'call_me') var called_with_4 = get_call_parameters(double_foo, 'call_me', 4) ``` -------------------------------- ### Spy on Test Doubles in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Demonstrates how to verify method calls on test doubles using assertion helpers to ensure expected interactions occurred. ```gdscript var double_foo = double(Foo).new() # ... perform actions ... assert_called(double_foo, 'bar') assert_not_called(double_foo, 'something') assert_call_count(double_foo, 'call_me', 10) ``` -------------------------------- ### Create Basic Tests in Godot Source: https://gut.readthedocs.io/en/latest/Quick-Start.html This GDScript snippet demonstrates how to create two basic unit tests using the GUT framework. It includes a passing test and a failing test using `assert_eq`. ```gdscript extends GutTest func test_passes(): # this test will pass because 1 does equal 1 assert_eq(1, 1) func test_fails(): # this test will fail because those strings are not equal assert_eq('hello', 'goodbye') ``` -------------------------------- ### Creating Parameterized Tests Source: https://gut.readthedocs.io/en/latest/Quick-Start.html Explains how to run tests multiple times with different input values using the use_parameters helper. Supports both standard arrays and named parameters for better test readability. ```GDScript var test_params = [[1, 2, 3], [4, 5, 6]] func test_with_parameters(p=use_parameters(test_params)): assert_eq(p[0], p[2] - p[1]) # The first array contains the name of the parameters, the 2nd array contains the values. var named_params = ParameterFactory.named_parameters(['a', 'b'], [[1, 2], ['one', 'two']]) func test_with_named_params(p=use_parameters(better_params)): assert_ne(p.a, p.b) ``` -------------------------------- ### Asynchronous Testing with Await Source: https://gut.readthedocs.io/en/latest/Quick-Start.html Provides methods to pause test execution for specific durations, signal emissions, or engine frame cycles. Essential for testing time-dependent logic or deferred object interactions. ```GDScript await wait_seconds(10) var my_obj = load('res://my_obj.gd').new() await wait_for_signal(my_obj.some_signal, 3) await wait_physics_frames(5) await wait_process_frames(10) ``` -------------------------------- ### Comprehensive GUT Signal Connection Example Source: https://gut.readthedocs.io/en/latest/Global-Lifecycle-Hooks.html A GDScript example demonstrating how to connect custom functions to all major GUT lifecycle signals (start_run, start_script, start_test, end_test, end_script, end_run) within a Pre-Run Hook script. It includes placeholder logic for handling test and script events. ```gdscript extends GutHookScript const NO_TEST := "__NO_TEST__" var _current_test_script_object = null var _current_collected_script = null var _current_test_name := NO_TEST func run(): gut.start_run.connect(_on_run_started) gut.start_script.connect(_on_script_started) gut.start_test.connect(_on_test_started) gut.end_test.connect(_on_test_ended) gut.end_script.connect(_on_script_ended) gut.end_run.connect(_on_run_ended) # Do pre-run stuff here # This might be redundant, and it might have already been emitted by the time # this hook is called. I wanted it in here for illustration purposes. func _on_run_started(): pass # This is passed an instance of res://addons/gut/collected_script.gd. It is not # the instance of the script that will be run. You can get to the script object # using `load_script`, but you can't get to the actual instance that will be # run. func _on_script_started(collected_script): _current_collected_script = collected_script # The GutTest script, not the instance. _current_test_script_object = collected_script.load_script() # _current_collected_script.get_full_name() returns the path of the file # that contains the test # This is just the name of the test method being ran. func _on_test_started(test_name): _current_test_name = test_name func _on_test_ended(): # example of inspecing the test that ended if you wanted to. var failed = _current_collected_script.get_test_named(_current_test_name).is_failing() if (failed): print(_current_test_name + " failed") else: print(_current_test_name + " passed") _current_test_name = NO_TEST func _on_script_ended(): #example of inspecing the script that ended if you wanted to if(!_current_collected_script.was_skipped): if(_current_collected_script.get_fail_count() > 0): print("The script ", _current_collected_script.get_full_name(), " failed") else: print("The script ", _current_collected_script.get_full_name(), " passed") _current_collected_script = null _current_test_script_object = null # I'm not sure if this is called before or after the post-run hook. This can't func _on_run_ended(): pass ``` -------------------------------- ### Organize Tests with Inner Classes in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Demonstrates grouping related tests using inner classes that extend GutTest, allowing for cleaner test organization within a single script file. ```gdscript extends GutTest class TestSomeAspects: extends GutTest func test_assert_eq_number_not_equal(): assert_eq(1, 2, "Should fail. 1 != 2") func test_assert_eq_number_equal(): assert_eq('asdf', 'asdf', "Should pass") class TestOtherAspects: extends GutTest func test_assert_true_with_true(): assert_true(true, "Should pass, true is true") ``` -------------------------------- ### Extend GutTest Base Class Source: https://gut.readthedocs.io/en/latest/Quick-Start.html This GDScript snippet shows the fundamental requirement for creating a test script in GUT: extending the `GutTest` base class. This is a minimal example to illustrate inheritance. ```gdscript extends GutTest ``` -------------------------------- ### Manage Object Lifecycle with Autofree in GUT Source: https://gut.readthedocs.io/en/latest/Memory-Management.html Demonstrates how to handle node instantiation in tests. The first example shows a potential orphan creation, while the second uses add_child_autofree to ensure the node is cleaned up automatically. ```GDScript func test_something(): var my_node = Node.new() assert_not_null(my_node) ``` ```GDScript func test_something(): # add_child_autofree will add the result of Node.new() to the tree, # mark it to be freed after the test, and return the instance created by # Node.new(). var my_node = add_child_autofree(Node.new()) assert_not_null(my_node) ``` -------------------------------- ### Applying stub actions Source: https://gut.readthedocs.io/en/latest/Stubbing.html Examples of specific stub actions including returning values, doing nothing, and calling the super implementation. ```GDScript stub(MyScript, "some_method").to_return(9) var inst = partial_double(MyScript).new() stub(inst._set).to_do_nothing() var dbl_inst = double(MyScript).new() stub(dbl_inst.some_method).to_call_super() ``` -------------------------------- ### Group Tests with Inner Classes in Godot Source: https://gut.readthedocs.io/en/latest/Quick-Start.html This GDScript snippet demonstrates how to organize tests using inner classes in GUT. Each inner class must extend `GutTest` and its name must start with 'Test'. ```gdscript extends GutTest class TestSomeAspects: extends GutTest func test_assert_eq_number_not_equal(): assert_eq(1, 2, "Should fail. 1 != 2") func test_assert_eq_number_equal(): assert_eq('asdf', 'asdf', "Should pass") class TestOtherAspects: extends GutTest func test_assert_true_with_true(): assert_true(true, "Should pass, true is true") ``` -------------------------------- ### Implement a basic GutTest script Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html This example demonstrates how to extend the GutTest class to define lifecycle methods and test functions. It uses the assert_eq method to perform equality checks between values. ```GDScript extends GutTest func before_all(): gut.p("before_all called") func before_each(): gut.p("before_each called") func after_each(): gut.p("after_each called") func after_all(): gut.p("after_all called") func test_assert_eq_letters(): assert_eq("asdf", "asdf", "Should pass") func test_assert_eq_number_not_equal(): assert_eq(1, 2, "Should fail. 1 != 2") ``` -------------------------------- ### Get Elapsed Microseconds Since Test Start Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Returns the total number of microseconds that have elapsed since the beginning of the current test method, as an integer. ```gdscript int get_elapsed_usec() ``` -------------------------------- ### Get Elapsed Milliseconds Since Test Start Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Returns the total number of milliseconds that have elapsed since the beginning of the current test method, as an integer. ```gdscript int get_elapsed_msec() ``` -------------------------------- ### Get Elapsed Seconds Since Test Start Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Returns the total number of seconds that have elapsed since the beginning of the current test method, as a floating-point number. ```gdscript float get_elapsed_sec() ``` -------------------------------- ### GUT configuration file structure Source: https://gut.readthedocs.io/en/latest/Command-Line.html A sample JSON configuration file for GUT that allows users to define test directories, strategies, and execution preferences without passing long command-line arguments. ```json { "dirs":["res://test/unit/","res://test/integration/"], "double_strategy":"partial", "ignore_pause":false, "include_subdirs":true, "inner_class":"", "log_level":3, "opacity":100, "prefix":"test_", "selected":"", "should_exit":true, "should_maximize":true, "suffix":".gd", "tests":[], "unit_test_name":"" } ``` -------------------------------- ### Asynchronous Waiting in Tests Source: https://gut.readthedocs.io/en/latest/_sources/Quick-Start.md.txt Provides methods to pause test execution for specific durations, signals, or frame counts. Essential for testing time-dependent logic or signal-driven events. ```gdscript await wait_seconds(10) var my_obj = load('res://my_obj.gd').new() await wait_for_signal(my_obj.some_signal, 3) await wait_physics_frames(5) await wait_process_frames(10) ``` -------------------------------- ### Basic Input Simulation with InputSender Source: https://gut.readthedocs.io/en/latest/_sources/Mocking-Input.md.txt Demonstrates how to press and hold an action for a duration, wait for it to complete, and then assert the outcome. This is useful for testing actions that have a time component. It requires the InputSender class and a receiver for the input events. ```gdscript extends GutTest var _sender = InputSender.new(Input) func after_each(): _sender.release_all() _sender.clear() func test_tapping_jump_jumps_certain_height(): var player = add_child_autofree(Player.new()) _sender.action_down("jump").hold_for(.1).wait(.3) await(_sender.idle) assert_between(player.position.y, 4, 5) ``` -------------------------------- ### Execute GUT tests via command line Source: https://gut.readthedocs.io/en/latest/Command-Line.html Demonstrates how to run the GUT test runner script using the Godot executable. It includes flags for debug mode, test file selection, log levels, and automatic exit behavior. ```bash godot -s addons/gut/gut_cmdln.gd -d --path "$PWD" -gtest=res://test/unit/sample_tests.gd -glog=1 -gexit ``` ```bash godot -s addons/gut/gut_cmdln.gd -d --path "$PWD" -gdir=res://test/unit -gprefix=me_ -gsuffix=.res -gselect=only_me ``` -------------------------------- ### Mocking Input using the Global Input Singleton Source: https://gut.readthedocs.io/en/latest/Mocking-Input.html Shows how to use the global Input singleton as a receiver to simulate hardware input. This requires careful state management using release_all and clear in after_each hooks, and necessitates awaiting frames to ensure input processing. ```GDScript var _sender = InputSender.new(Input) func after_each(): _sender.release_all() _sender.clear() func test_shoot(): var player = Player.new() _sender.action_down("shoot").wait_frames(1) await(_sender.idle) assert_true(player.is_shooting()) ``` -------------------------------- ### Stubbing and Spying with Partial Doubles Source: https://gut.readthedocs.io/en/latest/Quick-Start.html Demonstrates how to create a partial double that retains original functionality while allowing specific methods to be stubbed or spied upon. This is useful for isolating units of code while maintaining default behavior for non-stubbed methods. ```GDScript var double_bar = partial_double(Bar).instance() # the foo method will do nothing always now stub(double_ba.foo).to_do_nothing() # the something method will return 27 when passed 32, # but act normally when passed anything else. stub(double_bar.something).to_return(27).when_passed(32) # example of spying assert_called(double_bar, 'other_thing') ``` -------------------------------- ### ParameterFactory.named_parameters: Extra Values Example Source: https://gut.readthedocs.io/en/latest/Parameterized-Tests.html Shows an example of `ParameterFactory.named_parameters` where the provided values array has more elements than the names array. This results in extra values being ignored, and the output is an array of dictionaries with only the specified names. ```GDScript # Example of extra values. This returns: # [{a:1}, {a:3}] ParameterFactory.named_parameters( ['a'], [ [1, 2], [3, 4] ]) ``` -------------------------------- ### Simulating Input Actions with GutInputSender Source: https://gut.readthedocs.io/en/latest/class_ref/class_gutinputsender.html Demonstrates how to simulate pressing and releasing input actions using the GutInputSender class. This is useful for testing character movement or interaction logic. ```GDScript var sender = GutInputSender.new() sender.add_receiver(my_node) # Simulate pressing a jump action and holding it for 10 frames sender.action_down('jump').hold_for("10f") # Clear state between tests sender.clear() ``` -------------------------------- ### Create Doubles for Classes and Scenes in Godot Source: https://gut.readthedocs.io/en/latest/Quick-Start.html This GDScript snippet shows how to create doubles (mocks) of Godot classes and scenes using GUT's `double` function. It demonstrates loading resources and creating new instances of the doubles. ```gdscript var Foo = load('res://foo.gd') var MyScene = load('res://my_scene.tscn') var double_foo = double(Foo).new() var double_scene = double(MyScene).instantiate() ``` -------------------------------- ### GDScript Partial Double Example Source: https://gut.readthedocs.io/en/latest/Partial-Doubles.html Demonstrates creating and using a partial double for a GDScript class. It shows how to stub methods to bypass original functionality while retaining it for unstubbed methods, and how to assert method calls. ```gdscript # res://foo.gd extends Node2D var _value = 10 func set_value(val): _value = val func get_value(): return _value ``` ```gdscript var Foo = load('res://script.gd') func test_things(): var partial = partial_double(Foo).new() stub(partial, 'set_value').to_do_nothing() partial.set_value(20) # stubbed so implementation bypassed. # since set_value was stubbed, and get_value was not, and since # this is a partial stub, then the original functionality of # get_value will be executed and _value is returned. assert_eq(partial.get_value(), 10) # unstubbed partial methods can be spied on. assert_called(partial, 'get_value') # stubbed methods can be spied on as well assert_called(partial, 'set_value', [20]) ``` -------------------------------- ### ParameterFactory.named_parameters: Insufficient Values Example Source: https://gut.readthedocs.io/en/latest/Parameterized-Tests.html Demonstrates `ParameterFactory.named_parameters` when the values array has fewer elements than the names array for some sets. Missing values are filled with `null`. The example shows how different input formats (single value vs. array) are handled. ```GDScript # Example of not enough values. This returns: # [{a:1, b:null}, {a:'oops', b:null}, {a:'one', b:'two'}] ParameterFactory.named_parameters( ['a', 'b'], [ [1], 'oops', ['one', 'two'] ]) ``` -------------------------------- ### Invalid `named_parameters` Usage Examples in GDScript Source: https://gut.readthedocs.io/en/latest/_sources/Parameterized-Tests.md.txt Illustrates incorrect usage of `ParameterFactory.named_parameters` in GDScript, demonstrating scenarios with extra values and insufficient values. These examples highlight how GUT handles such cases, resulting in ignored extra values or null assignments for missing ones. ```gdscript # Example of extra values. This returns: # [{a:1}, {a:3}] ParameterFactory.named_parameters( ['a'], [ [1, 2], [3, 4] ]) # Example of not enough values. This returns: # [{a:1, b:null}, {a:'oops', b:null}, {a:'one', b:'two'}] ParameterFactory.named_parameters( ['a', 'b'], [ [1], 'oops', ['one', 'two'] ]) ``` -------------------------------- ### Testing Input with Accumulated Input Enabled in GUT Source: https://gut.readthedocs.io/en/latest/_sources/Mocking-Input.md.txt Demonstrates how to test key presses and action triggers when accumulated input is enabled. Includes examples of using GutInputSender, waiting for frames, and manually flushing the input buffer to verify immediate input processing. ```gdscript extends GutTest var _sender = InputSender.new(Input) func before_all(): InputMap.add_action("jump") func after_each(): _sender.release_all() _sender.clear() func test_when_uai_enabled_input_not_processed_immediately(): _sender.key_down('a') assert_false(Input.is_key_pressed(KEY_A)) func test_when_uai_enabled_just_pressed_is_not_processed_immediately(): _sender.action_down('jump') assert_false(Input.is_action_just_pressed('jump')) func test_when_uai_enabled_waiting_makes_button_pressed(): # wait 10 frames. In testing, 6 frames failed, but 7 passed. Added 3 for # good measure. _sender.key_down(KEY_Y).wait('10f') await(_sender.idle) assert_true(_sender.is_key_pressed(KEY_Y)) assert_true(Input.is_key_pressed(KEY_Y)) func test_when_uai_enabled_flushig_buffer_sends_input_immediatly(): _sender.key_down('a') Input.flush_buffered_events() assert_true(Input.is_key_pressed(KEY_A)) func test_disabling_uai_sends_input_immediately(): Input.use_accumulated_input = false _sender.key_down('a') assert_true(Input.is_key_pressed(KEY_A)) # re-enable so we don't ruin other tests Input.use_accumulated_input = true func test_when_uai_enabled_flushing_buffer_just_pressed_is_processed_immediately(): _sender.action_down('jump') Input.flush_buffered_events() assert_true(Input.is_action_just_pressed('jump')) ``` -------------------------------- ### Execute GUT tests in a deployed game using GutControl Source: https://gut.readthedocs.io/en/latest/Running-On-Devices.html This script demonstrates how to initialize the GutControl node, load a configuration file, and connect to various test lifecycle signals to monitor test progress during runtime. ```GDScript extends Node2D @onready var _gut_control = $GutControl var _current_script_object = null var _current_test_name = null func _ready(): simple_setup() func simple_setup(): _gut_control.load_config_file('res://.gutconfig.json') func complex_setup(): _gut_control.load_config_file('res://.gutconfig.json') var config = _gut_control.get_config() config.options.should_exit = false config.options.should_exit_on_success = false config.options.compact_mode = false config.options.junit_xml_file = 'user://deployed_results.xml' _post_ready_setup.call_deferred() func _post_ready_setup(): var gut = _gut_control.get_gut() gut.start_run.connect(_on_gut_run_start) gut.start_script.connect(_on_gut_start_script) gut.end_script.connect(_on_gut_end_script) gut.start_test.connect(_on_gut_start_test) gut.end_test.connect(_on_gut_end_test) gut.end_run.connect(_on_gut_run_end) func _on_gut_run_start(): print('Starting tests') func _on_gut_start_script(script_obj): print(script_obj.get_full_name(), ' has ', script_obj.tests.size(), ' tests') _current_script_object = script_obj func _on_gut_end_script(): var pass_count = 0 for test in _current_script_object.tests: if(test.did_pass()): pass_count += 1 print(pass_count, '/', _current_script_object.tests.size(), " passed\n") _current_script_object = null func _on_gut_start_test(test_name): _current_test_name = test_name print(' ', test_name) func _on_gut_end_test(): var test_object = _current_script_object.get_test_named(_current_test_name) var status = "failed" if(test_object.did_pass()): status = "passed" elif(test_object.pending): status = "pending" print(' ', status) _current_test_name = null func _on_gut_run_end(): print('Tests Done') ``` -------------------------------- ### Godot 4.0: Basic set(val): and get(): Property Accessors Source: https://gut.readthedocs.io/en/latest/New-For-Godot-4.html Demonstrates the fundamental usage of the new `set(val):` and `get():` syntax in Godot 4.0 for defining property accessors. This replaces the older `setget` keyword, making property access more explicit. No external dependencies are required. ```gdscript var foo = 10: get(): return foo set(val): foo = val ``` -------------------------------- ### Instantiate Doubled Scene Source: https://gut.readthedocs.io/en/latest/_sources/Doubles.md.txt Demonstrates how to create an instance of a doubled scene using GUT. This involves calling the instantiate() method on the doubled scene object. It shows two alternative ways to achieve this. ```gdscript var doubled_scene = DoubledScene.instantiate() # or var doubled_scene = double(MyScene).instantiate() ``` -------------------------------- ### Godot 4.0: set(val): and get(): with Backing Variable Source: https://gut.readthedocs.io/en/latest/New-For-Godot-4.html Illustrates how to implement `set(val):` and `get():` accessors in Godot 4.0 using a backing variable (`_foo`) to prevent unintended signal emissions or logic execution when setting the property internally. This is crucial for managing internal state changes. ```gdscript var _foo = 10 var foo = 10: get(): return _foo set(val): _foo = val foo_changed.emit() ``` -------------------------------- ### Parameterized Test with `ParameterFactory.named_parameters` Source: https://gut.readthedocs.io/en/latest/Parameterized-Tests.html Illustrates using `ParameterFactory.named_parameters` to create structured parameters for a test. The `test_foo` function receives a `params` object, allowing access to parameters by name (e.g., `params.p1`, `params.p2`, `params.result`). This method is useful for making tests more readable when dealing with multiple parameters. The example uses the same `Foo` class and `add` method as the previous example. ```GDScript # With this setup, you can use `params.p1`, `params.p2`, and # `params.result` in the test below. var foo_params = ParameterFactory.named_parameters( ['p1', 'p2', 'result'], # names [ [1, 2, 3], ['a', 'b', 'c'] ]) func test_foo(params = use_parameters(foo_params)): var foo = Foo.new() var result = foo.add(params.p1, params.p2) assert_eq(result, params.result) ``` -------------------------------- ### GET /get_missing_required_options Source: https://gut.readthedocs.io/en/latest/class_ref/class_addons_gut_cli_optparse.html Retrieves a list of required options that were not provided during the parsing process. ```APIDOC ## GET /get_missing_required_options ### Description Get all options that were required and were not set during parsing. ### Method GET ### Endpoint /get_missing_required_options ### Response #### Success Response (200) - **missing_options** (Array) - An array of Option objects that were required but missing. #### Response Example { "missing_options": ["config_file", "output_dir"] } ``` -------------------------------- ### Testing with Partial Double Singletons Source: https://gut.readthedocs.io/en/latest/Doubling-Singletons.html Shows how to create a partial double of an Engine Singleton and stub its methods to control test outcomes. ```GDScript extends GutTest func test_player_does_something_with_input(): var dbl_input = partial_double_singleton(Input).new() var p = Player.new() p.my_local_input_singleton_ref = dbl_input stub(dbl_input.is_action_just_pressed)\ .to_return(true)\ .when_passed("jump") ``` -------------------------------- ### Get Elapsed Process Frames Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Returns the number of process frames that have passed since the beginning of the current test method. ```gdscript int get_elapsed_process_frames() ``` -------------------------------- ### Verify Memory Leaks with assert_no_new_orphans Source: https://gut.readthedocs.io/en/latest/Memory-Management.html Shows how to validate that objects are properly freed after use. Includes examples for standard freeing and handling nodes added to the scene tree. ```GDScript class TestLeaks: extends GutTest var Foo = load('res://foo.gd') func test_no_leaks(): var to_free = Foo.new() to_free.free() assert_not_new_orphans() func test_no_leaks_with_add_child(): var to_free = Foo.new() add_child(to_free) to_free.free() assert_no_new_orphans() ``` -------------------------------- ### POST /parse_cli_args Source: https://gut.readthedocs.io/en/latest/class_ref/class_addons_gut_cli_optparse.html Parses a string for all options set in the optparse or defaults to Godot engine startup arguments. ```APIDOC ## POST /parse_cli_args ### Description Parses a string for all options that have been set in this optparse. If `cli_args` is passed as a String, it is parsed; otherwise, arguments passed to the Godot engine at startup are parsed. ### Method POST ### Endpoint /parse_cli_args ### Parameters #### Request Body - **cli_args** (String) - Optional - The string of arguments to parse. If null, defaults to engine startup arguments. ### Request Example { "cli_args": "-gtest_prefix=test_" } ### Response #### Success Response (200) - **status** (String) - Confirmation of parsing completion. #### Response Example { "status": "success" } ``` -------------------------------- ### GET /get_call_parameters Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Retrieves the parameters used in a method call for a doubled object. Useful for verifying that specific methods were called with expected arguments. ```APIDOC ## GET /get_call_parameters ### Description Returns the parameters for a method call to a doubled object. Can target a specific call index. ### Method GET ### Parameters #### Query Parameters - **object** (Object) - Required - The doubled object. - **method_name_or_index** (String/int) - Required - The method name or index of the call. - **idx** (int) - Optional - The specific call index to retrieve. ### Response #### Success Response (200) - **parameters** (Array) - The arguments passed to the method. #### Response Example { "parameters": [10, "test"] } ``` -------------------------------- ### Injecting Engine Singletons for Testing Source: https://gut.readthedocs.io/en/latest/Doubling-Singletons.html Demonstrates the pattern of using a local variable reference for an Engine Singleton to allow for dependency injection during testing. ```GDScript class_name Player var my_local_input_singleton_ref := Input func _physics_process(delta): if(my_local_input_singleton_ref.is_action_just_pressed("jump")): pass ``` -------------------------------- ### GET /get_signal_parameters Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Retrieves the parameters emitted by a specific signal on a watched object. By default, it returns the most recent emission, but specific indices can be requested. ```APIDOC ## GET /get_signal_parameters ### Description Retrieves the parameters emitted by a signal. Returns an array of values or null if the signal was not fired or not watched. ### Method GET ### Parameters #### Query Parameters - **object** (Object) - Required - The object being watched. - **signal_name** (String) - Required - The name of the signal. - **index** (int) - Optional - The index of the emission to retrieve (default: -1 for most recent). ### Response #### Success Response (200) - **parameters** (Array) - The list of arguments passed to the signal emission. #### Response Example { "parameters": ["a", "b", "c"] } ``` -------------------------------- ### Simulating Complex Special Move Inputs with InputSender Source: https://gut.readthedocs.io/en/latest/_sources/Mocking-Input.md.txt Illustrates how to simulate complex input sequences required for special moves, such as fighting game inputs. This involves chaining multiple directional and button presses within a short timeframe. It requires careful sequencing of `action_down` and `key_down` calls. ```gdscript extends GutTest var _sender = InputSender.new(Input) func after_each(): _sender.release_all() _sender.clear() func test_fireball_input(): var player = add_child_autofree(Player.new()) _sender.action_down("down").hold_for("2f") .action_down("down_forward").hold_for("2f") .action_down("forward").key_down("FP") await(_sender.idle) assert_true(player.is_throwing_fireball()) ``` -------------------------------- ### Get Elapsed Idle Frames Source: https://gut.readthedocs.io/en/latest/class_ref/class_guttest.html Returns the number of idle frames that have passed since the beginning of the current test method. This is an alias for wait_process_frames. ```gdscript int get_elapsed_idle_frames() ``` -------------------------------- ### Doubling a Script in GUT Source: https://gut.readthedocs.io/en/latest/Doubles.html Demonstrates how to load a script and create a doubled instance using the double() method. The resulting object can be instantiated like a standard class. ```GDScript var MyScript = load('res://my_script.gd') # Load the doubled object. var DoubledMyScript = double(MyScript) # Create an instance of a doubled object var doubled_script = DoubledMyScript.new() # or var doubled_script = double(MyScript).new() ```