### assert_file_does_not_exist test setup and examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts a file does not exist at the specified path. The example includes before_each and after_each setup and shows passing and failing cases. ```GDScript func before_each(): gut.file_touch('user://some_test_file') func after_each(): gut.file_delete('user://some_test_file') func test_assert_file_does_not_exist(): # Passing assert_file_does_not_exist('user://file_does_not.exist') assert_file_does_not_exist('res://some_dir/another_dir/file_does_not.exist') # Failing assert_file_does_not_exist('res://addons/gut/gut.gd') ``` -------------------------------- ### assert_file_not_empty test setup and examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts the specified file is not empty. The example includes before_each and after_each setup and shows passing and failing cases. ```GDScript func before_each(): gut.file_touch('user://some_test_file') func after_each(): gut.file_delete('user://some_test_file') func test_assert_file_not_empty(): # Passing assert_file_not_empty('res://addons/gut/gut.gd') # PASS # Failing assert_file_not_empty('user://some_test_file') # FAIL ``` -------------------------------- ### assert_file_empty test setup and examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts the specified file is empty. The example includes before_each and after_each setup and shows passing and failing cases. ```GDScript func before_each(): gut.file_touch('user://some_test_file') func after_each(): gut.file_delete('user://some_test_file') func test_assert_file_empty(): # Passing assert_file_empty('user://some_test_file') # Failing assert_file_empty('res://addons/gut/gut.gd') ``` -------------------------------- ### Test script with setup/teardown and asserts Source: https://gut.readthedocs.io/en/v9.7.1/Quick-Start.html Example test script showing before_all, before_each, after_each, after_all methods and two test methods using assert_eq. Any method starting with 'test' runs as a test. ```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") ``` -------------------------------- ### assert_file_exists test setup and examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts a file exists at the specified path. The example includes before_each and after_each setup using gut.file_touch and gut.file_delete, and shows passing and failing cases. ```GDScript func before_each(): gut.file_touch('user://some_test_file') func after_each(): gut.file_delete('user://some_test_file') func test_assert_file_exists(): # Passing assert_file_exists('res://addons/gut/gut.gd') assert_file_exists('user://some_test_file') # Failing assert_file_exists('user://file_does_not.exist') assert_file_exists('res://some_dir/another_dir/file_does_not.exist') ``` -------------------------------- ### GutControl Example Script for Deployed Tests Source: https://gut.readthedocs.io/en/v9.7.1/Running-On-Devices.html Full example script for running GUT tests on devices. Requires a scene with a GutControl node named 'GutControl'. Loads config from 'res://.gutconfig.json'. Includes simple and complex setup, signal connections, and a button handler to run tests. ```GDScript # ------------------------------------------------------------------------------ # This is an example of using the GutControl (res://addons/gut/gui/GutContro.tscn) # to execute tests in a deployed game. # # Setup: # Create a scene. # Add a GutControl to your scene, name it GutControl. # Add this script to your scene. # Run it. # ------------------------------------------------------------------------------ extends Node2D @onready var _gut_control = $GutControl # Holds a reference to the current test script object being run. Set in # signal callbacks. var _current_script_object = null # Holds the name of the current test being run. Set in signal callbacks. var _current_test_name = null func _ready(): simple_setup() # complex_setup() func simple_setup(): # You must load a gut config file to use this control. Here we are loading # the default config file used by the command line. You can use any config # file you have created. Use the "save as" button in the Settings subpanel # to create a config file, or write your own. # # Some settings may not work. For example, the exit flags do not have any # effect. # # Settings are not saved, so any changes will be lost. The idea is that you # want to deploy the settings and users should not be able to save them. If # you want to save changes, you can call: # _gut_control.get_config().write_options(path). # Note that you cannot to write to res:// on mobile platforms, so you will # have to juggle the initial loading from res:// or user:// and save to # user://. _gut_control.load_config_file('res://.gutconfig.json') # That's it. Just get a reference to the control you added to the scene and # give it a config. The rest of the stuff in this script optional. func complex_setup(): # See simple setup _gut_control.load_config_file('res://.gutconfig.json') # Returns a gut_config.gd instance. var config = _gut_control.get_config() # Override specific values for the purposes of this scene. You can see all # the options available in the default_options dictionary in gut_config.gd. # Changing settings AFTER _ready will not have any effect. config.options.should_exit = false config.options.should_exit_on_success = false config.options.compact_mode = false # Note that if you are exporting xml results you may want to set the path to # a file in user:// instead of an absolute path. Your game may not have # permissions to save files elsewhere when running on a mobile device. config.options.junit_xml_file = 'user://deployed_results.xml' # Some actions cannot be done until after _ready has finished in all objects _post_ready_setup.call_deferred() # If you would like to connect to signals provided by gut.gd then you must do # so after _ready. This is an example of getting a reference to gut and all # of the signals it provides. 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) # ----------------------- # Events # ----------------------- func _on_gut_run_start(): print('Starting tests') # This signal passes a TestCollector.gd/TestScript instance 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(): # get_test_named returns a TestCollector.gd/Test instance for the name # passed in. 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') # You can kick of the tests via code if you want. func _on_run_gut_tests_button_pressed(): _gut_control.run_tests() ``` -------------------------------- ### GutTest Example with InputSender Setup and Teardown Source: https://gut.readthedocs.io/en/v9.7.1/Mocking-Input.html Complete example of a GutTest class that sends inputs to Input. Defines the InputSender at class level and uses after_each to release_all and clear to prevent input leaking between tests. ```GDScript extends GutTest # When sending events to Input the InputSender instance should be defined at # the class level so that you can easily clear it between tests in after_each. var _sender = InputSender.new(Input) # IMPORTANT: When using Input as the receiver of events you should always # release_all and clear the InputSender so that any # actions/keys/buttons that are not released in a test are released # before the next test runs. "down" events will not be sent by # Input if the action/button/etc is currently "down". func after_each(): _sender.release_all() _sender.clear() # In this test we press and hold the jump button for .1 seconds then wait # another .3 seconds for the jump to take take place. We then assert that # the character has moved up between 4 and 5 pixels. 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) # This is similar to the other test but we hold jump for longer and then # verify the player jumped higher. func test_holding_jump_jumps_higher(): var player = add_child_autofree(Player.new()) _sender.action_down("jump").hold_for(.75) await(_sender.idle) assert_between(player.position.y, 7, 8) # This tests throwing a fireball, like with Ryu or Ken from Street Fighter. # Note that there is not a hold_for after "forward" and the key_down for # fierce punch (FP) immediately after. This means the "forward" motion AND # FP are pressed in the same frame. 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()) # In this example we are testing that two actions in combination cause the # player to slide. Note that there is no release of the actions in this # test. This is a good example of why using release_all in after_each makes # the tests simpler to write and prevents leaking of inputs from one test to # another. func test_holding_down_and_jump_does_slide(): var player = add_child_autofree(Player.new()) _sender.action_down("down").wait("1f")\ .action_down("jump").wait("2f") await(_sender.idle) assert_gt(player.velocity.x, 0) ``` -------------------------------- ### Inner test classes example Source: https://gut.readthedocs.io/en/v9.7.1/Creating-Tests.html Shows how to group tests using inner classes that start with 'Test' and extend GutTest. Each inner class can have its own setup and test methods. ```GDScript extends GutTest class TestFeatureA: extends GutTest var Obj = load('res://scripts/object.gd') var _obj = null func before_each(): _obj = Obj.new() func test_something(): assert_true(_obj.is_something_cool(), 'Should be cool.') class TestFeatureB: extends GutTest var Obj = load('res://scripts/object.gd') var _obj = null func before_each(): _obj = Obj.new() func test_foobar(): assert_eq(_obj.foo(), 'bar', 'Foo should return bar') ``` -------------------------------- ### Gut InputSender with Input as receiver - setup and test example Source: https://gut.readthedocs.io/en/v9.7.1/Mocking-Input.html Declare the InputSender at class level, release and clear it in after_each, and await before asserting. This ensures Input doesn't retain button states and objects process the frame. ```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()) ``` -------------------------------- ### Pre-run hook script to connect to start_test signal Source: https://gut.readthedocs.io/en/v9.7.1/Global-Lifecycle-Hooks.html Example of a pre-run hook script that connects a custom function to the gut.start_test signal. The _on_test_started function will be called before every test method in every test script, allowing you to define global setup logic once. ```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 ``` -------------------------------- ### Simple GutTest Example Script Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows the basic structure of a GUT test script extending GutTest, including lifecycle hooks (before_all, before_each, after_each, after_all) and example assertions using assert_eq. ```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") ``` -------------------------------- ### GUT orphan list example Source: https://gut.readthedocs.io/en/v9.7.1/Memory-Management.html Example output showing orphans created in tests, with node names, string representations, and descendant counts. ```plaintext * test_this_makes_two_orphans 2 Orphans * test_two_one: * test_two_two: * test_with_a_scene_orphan 104 Orphans * main:(main.gd) + 27 * GutRunner:(GutRunner.gd) + 75 ``` -------------------------------- ### Example of using simulate with _process and _physics_process Source: https://gut.readthedocs.io/en/v9.7.1/Simulate.html This example shows how to use gut.simulate to call _process and _physics_process on a tree of objects. It includes two custom objects and a test that verifies the methods are called. Note that nodes must be added to the tree (e.g., with add_child_autofree) to be processed by default. ```GDScript # -------------------------------- # res://scripts/my_object.gd # -------------------------------- extends Node2D var a_number = 1 func _process(delta): a_number += 1 # -------------------------------- # res://scripts/another_object.gd # -------------------------------- extends Node2D var another_number = 1 func _physics_process(delta): another_number += 1 # -------------------------------- # res://test/unit/test_my_object.gd # -------------------------------- # ... var MyObject = load('res://scripts/my_object.gd') var AnotherObject = load('res://scripts/another_object') # ... # Given that SomeCoolObj has a _process method that increments a_number by 1 # each time _process is called, and that the number starts at 0, this test # should pass func test_does_something_each_loop(): var my_obj = MyObject.new() add_child_autofree(my_obj) gut.simulate(my_obj, 20, .1) assert_eq(my_obj.a_number, 20, 'Since a_number is incremented in _process, it should be 20 now') # Let us also assume that AnotherObj acts exactly the same way as # but has SomeCoolObj but has a _physics_process method instead of # _process. In that case, this test will pass too since all child objects # have the _process or _physics_process method called. func test_does_something_each_loop(): var my_obj = MyObject.new() var other_obj = AnotherObj.new() add_child_autofree(my_obj) my_obj.add_child(other_obj) gut.simulate(my_obj, 20, .1) assert_eq(my_obj.a_number, 20, 'Since a_number is incremented in _process, \ it should be 20 now') assert_eq(other_obj.another_number, 20, 'Since other_obj is a child of my_obj \ and another_number is incremented in \ _physics_process then it should be 20 now') ``` -------------------------------- ### Double Singleton Example: Test Script Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows how to create a partial double of the Time singleton and inject it into an instance of UsesTime. This is the test script part of the double_singleton example. ```GDScript extends GutTest func test_something(): var dbl_time = partial_double_singleton(Time).new() var inst = UsesTime.new() inst.t = dbl_time ``` -------------------------------- ### UsesTime class using Time singleton Source: https://gut.readthedocs.io/en/v9.7.1/Doubling-Singletons.html Example class that uses the Time singleton via a local reference (t) so it can be injected with a double. Includes start() and end() methods that use get_ticks_msec and get_date_dict_from_system. ```GDScript class_name UsesTime # Must have a reference to Engine Singleton that we can # inject our double into. 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 ``` -------------------------------- ### Example script res://foo.gd Source: https://gut.readthedocs.io/en/v9.7.1/Partial-Doubles.html A sample script used to demonstrate partial doubles. It has a _value variable and set_value/get_value methods. ```gdscript # res://foo.gd extends Node2D var _value = 10 func set_value(val): _value = val func get_value(): return _value ``` -------------------------------- ### Static Method Doubling Error Example Source: https://gut.readthedocs.io/en/v9.7.1/Doubles.html Example error message shown when trying to double a class with a static method. GUT cannot detect static methods, so this error occurs. ```Plain Text Parser Error: Function signature doesn't match the parent. Parent signature is: 'Variant foo()'. ``` -------------------------------- ### GutTest Class Overview Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Overview of the GutTest class, including its inheritance, properties, and a simple example of a test script. ```APIDOC # GutTest Class Reference **Inherits:** Node This is the base class for your GUT test scripts. GUT Wiki: https://gut.readthedocs.io ## Simple Example ```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") ``` ## Properties | Variant | DOUBLE_STRATEGY | `{"INCLUDE_NATIVE": 0, "SCRIPT_ONLY": 1}` | | --- | --- | --- | | Variant | ParameterFactory | `` | | Variant | InputFactory | `GutInputFactory` | | Variant | InputSender | `` | | GutMain | gut | `null` | | Variant | collected_script | `null` | | Variant | wait_log_delay | `0.5` | ## Methods | Variant | add_child_autofree(node, legible_unique_name = false) | | Variant | add_child_autoqfree(node, legible_unique_name = false) | | void | after_all() | | void | after_each() | | void | assert_accessors(obj, property, default, set_to) | | void | assert_almost_eq(got, expected, error_interval, text = "") | | void | assert_almost_ne(got, not_expected, error_interval, text = "") | | void | assert_between(got, expect_low, expect_high, text = "") | | void | assert_called(inst, method_name = null, parameters = null) | | void | assert_called_count(callable: Callable, expected_count: int) | | void | assert_connected(p1, p2, p3 = null, p4 = null) | | void | assert_does_not_have(obj, element, text = "") | | void | assert_engine_error(text, msg = "") | | void | assert_engine_error_count(count: int, msg: String = "") | | void | assert_eq(got, expected, text = "") | | void | assert_eq_deep(v1, v2) | | void | assert_exports(obj, property_name, type) | | void | assert_false(got, text = "") | | void | assert_file_does_not_exist(file_path) | | void | assert_file_empty(file_path) | | void | assert_file_exists(file_path) | | void | assert_file_not_empty(file_path) | | void | assert_freed(obj, title = "something") | | void | assert_gt(got, expected, text = "") | | void | assert_gte(got, expected, text = "") | | void | assert_has(obj, element, text = "") | | void | assert_has_method(obj, method, text = "") | | void | assert_has_signal(object, signal_name, text = "") | | void | assert_is(object, a_class, text = "") | | void | assert_lt(got, expected, text = "") | | void | assert_lte(got, expected, text = "") | | void | assert_ne(got, not_expected, text = "") | | void | assert_ne_deep(v1, v2) | | void | assert_no_new_orphans(text = "") | | void | assert_not_between(got, expect_low, expect_high, text = "") | | void | assert_not_called(inst, method_name = null, parameters = null) | | void | assert_not_connected(p1, p2, p3 = null, p4 = null) | | void | assert_not_freed(obj, title = "something") | | void | assert_not_null(got, text = "") | | void | assert_not_same(v1, v2, text = "") | | void | assert_not_typeof(object, type, text = "") | | void | assert_null(got, text = "") | | void | assert_property(obj, property_name, default_value, new_value) | | void | assert_property_with_backing_variable(obj, property_name, default_value, new_value, backed_by_name = null) | | void | assert_push_error(text, msg = "") | | void | assert_push_error_count(count: int, msg: String = "") | | void | assert_push_warning(text: String, msg: String = "") | | void | assert_push_warning_count(count: int, msg: String = "") | | void | assert_same(v1, v2, text = "") | | void | assert_signal_emit_count(p1, p2, p3 = 0, p4 = "") | | void | assert_signal_emitted(p1, p2 = "", p3 = "") | | void | assert_signal_emitted_with_parameters(p1, p2, p3 = -1, p4 = -1) | | void | assert_signal_not_emitted(p1, p2 = "", p3 = "") | | void | assert_string_contains(text, search, match_case = true) | | void | assert_string_ends_with(text, search, match_case = true) | | void | assert_string_starts_with(text, search, match_case = true) | | void | assert_true(got, text = "") | | void | assert_typeof(object, type, text = "") | | Variant | autofree(thing) | | Variant | autoqfree(thing) | | void | before_all() | | void | before_each() | | Variant | compare_deep(v1, v2, max_differences = null) | | Variant | did_wait_timeout() | | Variant | double(thing, double_strat = null, not_used_anymore = null) | | Variant | double_singleton(singleton) | | void | fail_test(text) | | Variant | get_assert_count() | | Variant | get_call_count(object, method_name = null, parameters = null) | | Variant | get_call_parameters(object, method_name_or_index = -1, idx = -1) | | Variant | get_double_strategy() | | int | get_elapsed_idle_frames() | | int | get_elapsed_msec() | | int | get_elapsed_physics_frames() | ``` -------------------------------- ### assert_lt example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts got is less than expected. ```GDScript var bigger = 5 var smaller = 0 # Passing assert_lt(smaller, bigger, 'Smaller should be less than bigger') assert_lt('a', 'b') assert_lt(99, 100) # Failing assert_lt('z', 'x') assert_lt(-5, -5) ``` -------------------------------- ### assert_gt example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts got > expected. ```GDScript var bigger = 5 var smaller = 0 # Passing assert_gt(bigger, smaller, 'Bigger should be greater than smaller') assert_gt('b', 'a') assert_gt('a', 'A') assert_gt(1.1, 1) # Failing assert_gt('a', 'a') assert_gt(1.0, 1) assert_gt(smaller, bigger) ``` -------------------------------- ### Await wait_physics_frames Source: https://gut.readthedocs.io/en/v9.7.1/Awaiting.html Example of awaiting wait_physics_frames to pause execution for 10 physics frames. ```gdscript await wait_physics_frames(10) ``` -------------------------------- ### Stub to_call_super example Source: https://gut.readthedocs.io/en/v9.7.1/Stubbing.html Causes a method to call super's implementation, retaining original functionality. ```gdscript var dbl_inst = double(MyScript).new() var inst = double(MyScript).new() stub(dbl_inst.some_method).to_call_super() assert_eq(dbl_inst.some_method(), inst.some_method()) ``` -------------------------------- ### assert_called examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows various ways to call assert_called: with method name, with a Callable, with parameters, and with bound arguments. Requires a doubled instance. ```GDScript var my_double = double(Foobar).new() ... assert_called(my_double, 'foo') assert_called(my_double.foo) assert_called(my_double, 'foo', [1, 2, 3]) assert_called(my_double.foo.bind(1, 2, 3)) ``` -------------------------------- ### Partial Double Example Source: https://gut.readthedocs.io/en/v9.7.1/Quick-Start.html Create a partial double of Bar and stub or spy on its methods. Unstubbed methods retain their original behavior. ```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') ``` -------------------------------- ### skip_if_godot_version_lt example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows how to use skip_if_godot_version_lt to skip a test if the engine version is less than the expected version. The result of the check is returned. ```GDScript if(skip_if_godot_version_lt('3.5.0')): return ``` -------------------------------- ### Sample GUT test script (test_example.gd) Source: https://gut.readthedocs.io/en/v9.7.1/Creating-Tests.html Copy this script into res://test/unit/test_example.gd and run it. It demonstrates setup/teardown hooks and various assert functions, producing both passing and failing tests. ```GDScript extends GutTest func before_each(): gut.p("ran setup", 2) func after_each(): gut.p("ran teardown", 2) func before_all(): gut.p("ran run setup", 2) func after_all(): gut.p("ran run teardown", 2) 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") func test_assert_true_with_true(): assert_true(true, "Should pass, true is true") func test_assert_true_with_false(): assert_true(false, "Should fail") func test_something_else(): assert_true(false, "didn't work") ``` -------------------------------- ### assert_string_starts_with examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows passing and failing cases for assert_string_starts_with. Passing cases include case-sensitive and case-insensitive checks. Failing cases include case-sensitive mismatch and longer search strings. ```GDScript # Passing assert_string_starts_with('abc 123', 'a') assert_string_starts_with('abc 123', 'ABC', false) assert_string_starts_with('abc 123', 'abc 123') ## Failing assert_string_starts_with('abc 123', 'z') assert_string_starts_with('abc 123', 'ABC') assert_string_starts_with('abc 123', 'abc 1234') ``` -------------------------------- ### Sample GUT config file (.gutconfig.json) Source: https://gut.readthedocs.io/en/v9.7.1/Command-Line.html Sample JSON configuration file for GUT. By default, gut_cmdln looks for this file at res://.gutconfig.json. You can specify a different file using the -gconfig option. Print out the text for a gutconfig file using the -gprint_gutconfig_sample option. ```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":"", } ``` -------------------------------- ### _init(r = null) Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_gutinputsender.html Constructor that accepts a single optional receiver. ```APIDOC ## Method _init(r = null) ### Description Accepts a single optional receiver. ### Method void **_init**(r = null) ### Parameters - **r** (Variant) - Optional - Receiver object. ``` -------------------------------- ### print_help() Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Prints out the help text for all defined options. ```APIDOC ## print_help() ### Description Prints out the help text for all defined options. ### Method void print_help() ``` -------------------------------- ### Using ParameterFactory.named_parameters Source: https://gut.readthedocs.io/en/v9.7.1/Parameterized-Tests.html Creates an array of dictionaries by pairing names with each set of values. The test can then access values via named properties like params.p1, params.p2, and params.result. This example shows a valid setup with matching names and values. ```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 [ # values [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) ``` -------------------------------- ### assert_push_error_count() example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts the number of push_errors generated by the test. Each error can only be asserted against once. The example shows a test that pushes an error and asserts the count. ```GDScript func test_with_push_error(): push_error("This is an error") assert_push_error(1, 'This test should have caused a push_error') ``` -------------------------------- ### Double Singleton Example: UsesTime class Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Defines a class that uses the Time singleton. This is part of the example for double_singleton, showing how to create a class that can be injected with a double. ```GDScript class_name UsesTime var t := Time ``` -------------------------------- ### assert_connected example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows how to use assert_connected to verify signal connections. Passing cases include various argument forms; failing cases include wrong method, wrong signal, or wrong object. ```GDScript class Signaler: signal the_signal class Connector: func connect_this(): pass func other_method(): pass func test_assert_connected(): var signaler = Signaler.new() var connector = Connector.new() signaler.the_signal.connect(connector.connect_this) # Passing assert_connected(signaler.the_signal, connector.connect_this) assert_connected(signaler.the_signal, connector) assert_connected(signaler, connector, 'the_signal') assert_connected(signaler, connector, 'the_signal', 'connect_this') # Failing assert_connected(signaler.the_signal, connector.other_method) var foo = Connector.new() assert_connected(signaler, connector, 'the_signal', 'other_method') assert_connected(signaler, connector, 'other_signal') assert_connected(signaler, foo, 'the_signal') ``` -------------------------------- ### Help generation with headings and default substitution Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Shows how to add options with headings for help sections. Including '[default]' in an option's description substitutes the default value in the generated help. ```GDScript add("--asdf", 1, "This will have no heading") add_heading("foo") add("--foo", false, "This will have the foo heading") add("--another_foo", 1.5, "This too.") add_heading("This is after foo") add("--bar", true, "You probably get it by now.") ``` -------------------------------- ### Assert Engine Error Count with assert_engine_error_count Source: https://gut.readthedocs.io/en/v9.7.1/Error-Tracking.html Example test that uses assert_engine_error_count(2) to verify that exactly two engine errors were generated by the same operations as the previous example. ```GDScript func test_demo_engine_type_error(): assign_a_to_string_and_b_to_int(Object.new(), 'asdf') divide_recklessly('some words', Node) assert_engine_error_count(2) ``` -------------------------------- ### get_help() Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Returns the help text for all defined options. ```APIDOC ## get_help() ### Description Returns the help text for all defined options. ### Method String get_help() ### Returns - **String** - The help text for all defined options. ``` -------------------------------- ### GUT Error Output for Engine Errors Source: https://gut.readthedocs.io/en/v9.7.1/Error-Tracking.html Example output from GUT showing the engine errors generated by the previous example. It lists the error messages with indices and line numbers. ```plaintext [Failed]: Unexpected Errors: [1] Trying to assign value of type 'Object' to a variable of type 'String'. [2] Invalid operands 'String' and 'Object' in operator '/'. at line -1 ``` -------------------------------- ### assert_between passing and failing examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts value is between (inclusive) the two expected values. The example shows passing cases with integers and floats, and failing cases with strings and out-of-range values. ```GDScript # Passing assert_between(5, 0, 10, 'Five should be between 0 and 10') assert_between(10, 0, 10) assert_between(0, 0, 10) assert_between(2.25, 2, 4.0) # Failing assert_between('a', 'b', 'c') assert_between(1, 5, 10) ``` -------------------------------- ### Run GUT with directory, prefix, suffix, and select options Source: https://gut.readthedocs.io/en/v9.7.1/Command-Line.html Loads all test scripts that begin with 'me_' and end in '.res' and runs 'me_only_only_me.res' using -gdir, -gprefix, -gsuffix, and -gselect. Does not specify -gexit to allow running all scripts via the GUI afterward. ```bash godot -s addons/gut/gut_cmdln.gd -d --path "$PWD" -gdir=res://test/unit -gprefix=me_ -gsuffix=.res -gselect=only_me ``` -------------------------------- ### assert_not_between passing and failing examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts value is not between (exclusive) the two expected values. The example shows passing cases with integers, strings, and floats, and failing cases where the value is within the range. ```GDScript # Passing assert_not_between(1, 5, 10) assert_not_between('a', 'b', 'd') assert_not_between('d', 'b', 'd') assert_not_between(10, 0, 10) assert_not_between(-2, -2, 10) # Failing assert_not_between(5, 0, 10, 'Five shouldnt be between 0 and 10') assert_not_between(0.25, -2.0, 4.0) ``` -------------------------------- ### get_help() Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Returns the help text as a String. This method generates the help output for the options. ```APIDOC ## get_help() ### Description Returns the help text as a String. This method generates the help output for the options. ### Method get_help ### Returns - **String** - The help text. ``` -------------------------------- ### assert_has passing and failing examples Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Uses the 'has' method of the object to determine if it contains the element. The example shows passing cases with arrays and hashes, and failing cases with missing elements or incorrect types. ```GDScript var an_array = [1, 2, 3, 'four', 'five'] var a_hash = { 'one':1, 'two':2, '3':'three'} # Passing assert_has(an_array, 'four') # PASS assert_has(an_array, 2) # PASS # the hash's has method checks indexes not values assert_has(a_hash, 'one') # PASS assert_has(a_hash, '3') # PASS # Failing assert_has(an_array, 5) # FAIL assert_has(an_array, self) # FAIL assert_has(a_hash, 3) # FAIL assert_has(a_hash, 'three') # FAIL ``` -------------------------------- ### print_help() Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Prints the help text to the console. This method outputs the help information for the options. ```APIDOC ## print_help() ### Description Prints the help text to the console. This method outputs the help information for the options. ### Method print_help ``` -------------------------------- ### get_auto_flush_input() Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_gutinputsender.html Get the value of set_auto_flush_input. ```APIDOC ## Method get_auto_flush_input() ### Description Get the value of set_auto_flush_input. ### Method Variant **get_auto_flush_input**() ### Returns - **Variant** - The current auto flush setting. ``` -------------------------------- ### Using partial_double in a test Source: https://gut.readthedocs.io/en/v9.7.1/Partial-Doubles.html Shows how to create a partial double, stub a method to do nothing, and verify that unstubbed methods retain original functionality. Also demonstrates spying on both stubbed and unstubbed methods. ```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]) ``` -------------------------------- ### get_help Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Generates help text. ```APIDOC ## get_help ### Description Generates help text. ### Method get_help ### Returns String - The generated help text. ``` -------------------------------- ### get_errors() example: inspect and handle errors Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Shows how to use get_errors() to retrieve all errors generated by the test. Each error is a GutTrackedError; setting its handled property prevents it from causing test failure. The example marks all errors as handled after inspecting them. ```GDScript func divide_them(a, b): return a / b func test_with_script_error(): divide_them('one', 44) push_error('this is a push error') var errs = get_errors() assert_eq(errs.size(), 2, 'expected error count') # Maybe inspect some properties of the errors here. # Mark all the errors as handled. for e in errs: e.handled = true ``` -------------------------------- ### assert_push_error() example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts that a single push error containing the given text (case insensitive) was generated. If found, the assert passes and the test will not fail from that push_error. Each error can only be asserted against once. The example shows asserting for one error and for multiple errors. ```GDScript func test_push_error_text(): push_error("SpecialText") assert_push_error("CIALtex") func test_push_error_multiple_texts(): push_error("Error One") push_error("Expception two") assert_push_error("one") assert_push_error("two") ``` -------------------------------- ### GDScript: Test shooting with InputSender Source: https://gut.readthedocs.io/en/v9.7.1/Mocking-Input.html Creates a Player instance and an InputSender, sends an action_down event for 'shoot', and asserts the player is shooting. Recommended to create a new InputSender per test to avoid state retention. ```GDScript func test_shoot(): var player = Player.new() var sender = InputSender.new(player) sender.action_down("shoot") assert_true(player.is_shooting()) ``` -------------------------------- ### assert_engine_error() example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts that a single engine error containing the given text (case insensitive) was generated. If found, the assert passes and the test will not fail from that error. Each error can only be asserted against once. The example shows asserting for one error and for multiple errors. ```GDScript func divide_them(a, b): return a / b func test_asserting_engine_error_text(): divide_them('word', 91) assert_engine_error('invalid operands') func test_asserting_multipe_engine_error_texts(): divide_them('foo', Node) divide_them(1729, 0) assert_engine_error('Division by zero') assert_engine_error('invalid operands') ``` -------------------------------- ### print_help Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html Prints the help text. ```APIDOC ## print_help ### Description Prints the help text. ### Method print_help ``` -------------------------------- ### parse(cli_args = null) Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_addons_gut_cli_optparse.html 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. ```APIDOC ## parse(cli_args = null) ### Description Parses a string for all options that have been set in this optparse. If `cli_args` is passed as a String, then it is parsed. Otherwise if `cli_args` is null, arguments passed to the Godot engine at startup are parsed. ### Method void parse(cli_args = null) ### Parameters - **cli_args** (String, optional) - If provided, the string to parse. If null, uses startup arguments. ``` -------------------------------- ### assert_engine_error_count() example Source: https://gut.readthedocs.io/en/v9.7.1/class_ref/class_guttest.html Asserts the number of engine errors generated by the test. Each error can only be asserted against once; attempting to assert the same error twice will fail. The example shows a passing test, a test with zero errors, and a failing test that tries to count the same error twice. ```GDScript func divide_them(a, b): return a / b func test_asserting_engine_error_count(): divide_them('one', 44) assert_engine_error_count(1, "expecing a script error") func test_no_errors(): assert_engine_error_count(0, 'should be no errors here') func test_this_fails_cannot_assert_an_error_twice(): divide_them('one', 44) assert_engine_error_count(1, "expecing a script error") # this assert will fail because we already counted it. assert_engine_error_count(1, "expecing a script error") ``` -------------------------------- ### wait_until usage examples Source: https://gut.readthedocs.io/en/v9.7.1/Awaiting.html Examples showing how to use wait_until with a callable, optional message, and optional wait interval. The callable must return true (not a truthy value). The method returns true if the callable returned true before timeout, false otherwise. ```gdscript var everything_is_ok = func(): return true # Call everything_is_ok every frame until it returns true or 5 seconds elapses await wait_until(everything_is_ok, 5) # Same as above but we get the result to use later and provide a message to # display when the await starts. var result = await wait_until(everything_is_ok, 5, 'Show this message') # Calls everything_is_ok every second until it returns true and asserts # on the returned value assert_true(await wait_until(everything_is_ok, 10, 1), "Everything should be ok in 10 seconds"). ```