diff options
Diffstat (limited to 'addons/gut/test.gd')
| -rw-r--r-- | addons/gut/test.gd | 1687 |
1 files changed, 0 insertions, 1687 deletions
diff --git a/addons/gut/test.gd b/addons/gut/test.gd deleted file mode 100644 index 3fc0e8f..0000000 --- a/addons/gut/test.gd +++ /dev/null @@ -1,1687 +0,0 @@ -class_name GutTest -# ############################################################################## -#(G)odot (U)nit (T)est class -# -# ############################################################################## -# The MIT License (MIT) -# ===================== -# -# Copyright (c) 2020 Tom "Butch" Wesley -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ############################################################################## -# View readme for usage details. -# -# Version - see gut.gd -# ############################################################################## -# Class that all test scripts must extend. -# -# This provides all the asserts and other testing features. Test scripts are -# run by the Gut class in gut.gd -# ############################################################################## -extends Node - -# ------------------------------------------------------------------------------ -# Helper class to hold info for objects to double. This extracts info and has -# some convenience methods. This is key in being able to make the "smart double" -# method which makes doubling much easier for the user. -# ----------------------------------------------------------------------------- -class DoubleInfo: - var path - var subpath - var strategy - var make_partial - var extension - var _utils = load('res://addons/gut/utils.gd').get_instance() - var _is_native = false - var is_valid = false - - # Flexible init method. p2 can be subpath or stategy unless p3 is - # specified, then p2 must be subpath and p3 is strategy. - # - # Examples: - # (object_to_double) - # (object_to_double, subpath) - # (object_to_double, strategy) - # (object_to_double, subpath, strategy) - func _init(thing, p2=null, p3=null): - strategy = p2 - - # short-circuit and ensure that is_valid - # is not set to true. - if(_utils.is_instance(thing)): - return - - if(typeof(p2) == TYPE_STRING): - strategy = p3 - subpath = p2 - - if(typeof(thing) == TYPE_OBJECT): - if(_utils.is_native_class(thing)): - path = thing - _is_native = true - extension = 'native_class_not_used' - else: - path = thing.resource_path - else: - path = thing - - if(!_is_native): - extension = path.get_extension() - - is_valid = true - - func is_scene(): - return extension == 'tscn' - - func is_script(): - return extension == 'gd' - - func is_native(): - return _is_native - -# ------------------------------------------------------------------------------ -# Begin test.gd -# ------------------------------------------------------------------------------ -var _utils = load('res://addons/gut/utils.gd').get_instance() -var _compare = _utils.Comparator.new() - -# constant for signal when calling yield_for -const YIELD = 'timeout' - -# Need a reference to the instance that is running the tests. This -# is set by the gut class when it runs the tests. This gets you -# access to the asserts in the tests you write. -var gut = null - -var _disable_strict_datatype_checks = false -# Holds all the text for a test's fail/pass. This is used for testing purposes -# to see the text of a failed sub-test in test_test.gd -var _fail_pass_text = [] - -const EDITOR_PROPERTY = PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_DEFAULT -const VARIABLE_PROPERTY = PROPERTY_USAGE_SCRIPT_VARIABLE - -# Used with assert_setget -enum { - DEFAULT_SETTER_GETTER, - SETTER_ONLY, - GETTER_ONLY -} - -# Summary counts for the test. -var _summary = { - asserts = 0, - passed = 0, - failed = 0, - tests = 0, - pending = 0 -} - -# This is used to watch signals so we can make assertions about them. -var _signal_watcher = load('res://addons/gut/signal_watcher.gd').new() - -# Convenience copy of _utils.DOUBLE_STRATEGY -var DOUBLE_STRATEGY = null -var _lgr = _utils.get_logger() -var _strutils = _utils.Strutils.new() - -# syntax sugar -var ParameterFactory = _utils.ParameterFactory -var CompareResult = _utils.CompareResult -var InputFactory = _utils.InputFactory -var InputSender = _utils.InputSender - -func _init(): - DOUBLE_STRATEGY = _utils.DOUBLE_STRATEGY # yes, this is right - -func _str(thing): - return _strutils.type2str(thing) - -# ------------------------------------------------------------------------------ -# Fail an assertion. Causes test and script to fail as well. -# ------------------------------------------------------------------------------ -func _fail(text): - _summary.asserts += 1 - _summary.failed += 1 - _fail_pass_text.append('failed: ' + text) - if(gut): - _lgr.failed(text) - gut._fail(text) - -# ------------------------------------------------------------------------------ -# Pass an assertion. -# ------------------------------------------------------------------------------ -func _pass(text): - _summary.asserts += 1 - _summary.passed += 1 - _fail_pass_text.append('passed: ' + text) - if(gut): - _lgr.passed(text) - gut._pass(text) - -# ------------------------------------------------------------------------------ -# Checks if the datatypes passed in match. If they do not then this will cause -# a fail to occur. If they match then TRUE is returned, FALSE if not. This is -# used in all the assertions that compare values. -# ------------------------------------------------------------------------------ -func _do_datatypes_match__fail_if_not(got, expected, text): - var did_pass = true - - if(!_disable_strict_datatype_checks): - var got_type = typeof(got) - var expect_type = typeof(expected) - if(got_type != expect_type and got != null and expected != null): - # If we have a mismatch between float and int (types 2 and 3) then - # print out a warning but do not fail. - if([2, 3].has(got_type) and [2, 3].has(expect_type)): - _lgr.warn(str('Warn: Float/Int comparison. Got ', _strutils.types[got_type], - ' but expected ', _strutils.types[expect_type])) - else: - _fail('Cannot compare ' + _strutils.types[got_type] + '[' + _str(got) + '] to ' + \ - _strutils.types[expect_type] + '[' + _str(expected) + ']. ' + text) - did_pass = false - - return did_pass - -# ------------------------------------------------------------------------------ -# Create a string that lists all the methods that were called on an spied -# instance. -# ------------------------------------------------------------------------------ -func _get_desc_of_calls_to_instance(inst): - var BULLET = ' * ' - var calls = gut.get_spy().get_call_list_as_string(inst) - # indent all the calls - calls = BULLET + calls.replace("\n", "\n" + BULLET) - # remove trailing newline and bullet - calls = calls.substr(0, calls.length() - BULLET.length() - 1) - return "Calls made on " + str(inst) + "\n" + calls - -# ------------------------------------------------------------------------------ -# Signal assertion helper. Do not call directly, use _can_make_signal_assertions -# ------------------------------------------------------------------------------ -func _fail_if_does_not_have_signal(object, signal_name): - var did_fail = false - if(!_signal_watcher.does_object_have_signal(object, signal_name)): - _fail(str('Object ', object, ' does not have the signal [', signal_name, ']')) - did_fail = true - return did_fail - -# ------------------------------------------------------------------------------ -# Signal assertion helper. Do not call directly, use _can_make_signal_assertions -# ------------------------------------------------------------------------------ -func _fail_if_not_watching(object): - var did_fail = false - if(!_signal_watcher.is_watching_object(object)): - _fail(str('Cannot make signal assertions because the object ', object, \ - ' is not being watched. Call watch_signals(some_object) to be able to make assertions about signals.')) - did_fail = true - return did_fail - -# ------------------------------------------------------------------------------ -# Returns text that contains original text and a list of all the signals that -# were emitted for the passed in object. -# ------------------------------------------------------------------------------ -func _get_fail_msg_including_emitted_signals(text, object): - return str(text," (Signals emitted: ", _signal_watcher.get_signals_emitted(object), ")") - -# ------------------------------------------------------------------------------ -# This validates that parameters is an array and generates a specific error -# and a failure with a specific message -# ------------------------------------------------------------------------------ -func _fail_if_parameters_not_array(parameters): - var invalid = parameters != null and typeof(parameters) != TYPE_ARRAY - if(invalid): - _lgr.error('The "parameters" parameter must be an array of expected parameter values.') - _fail('Cannot compare paramter values because an array was not passed.') - return invalid - - -func _create_obj_from_type(type): - var obj = null - if type.is_class("PackedScene"): - obj = type.instance() - add_child(obj) - else: - obj = type.new() - return obj - - -# ####################### -# Virtual Methods -# ####################### - -# alias for prerun_setup -func before_all(): - pass - -# alias for setup -func before_each(): - pass - -# alias for postrun_teardown -func after_all(): - pass - -# alias for teardown -func after_each(): - pass - -# ####################### -# Public -# ####################### - -func get_logger(): - return _lgr - -func set_logger(logger): - _lgr = logger - - -# ####################### -# Asserts -# ####################### - -# ------------------------------------------------------------------------------ -# Asserts that the expected value equals the value got. -# ------------------------------------------------------------------------------ -func assert_eq(got, expected, text=""): - - if(_do_datatypes_match__fail_if_not(got, expected, text)): - var disp = "[" + _str(got) + "] expected to equal [" + _str(expected) + "]: " + text - var result = null - - if(typeof(got) == TYPE_ARRAY): - result = _compare.shallow(got, expected) - else: - result = _compare.simple(got, expected) - - if(typeof(got) in [TYPE_ARRAY, TYPE_DICTIONARY]): - disp = str(result.summary, ' ', text) - - if(result.are_equal): - _pass(disp) - else: - _fail(disp) - - -# ------------------------------------------------------------------------------ -# Asserts that the value got does not equal the "not expected" value. -# ------------------------------------------------------------------------------ -func assert_ne(got, not_expected, text=""): - if(_do_datatypes_match__fail_if_not(got, not_expected, text)): - var disp = "[" + _str(got) + "] expected to not equal [" + _str(not_expected) + "]: " + text - var result = null - - if(typeof(got) == TYPE_ARRAY): - result = _compare.shallow(got, not_expected) - else: - result = _compare.simple(got, not_expected) - - if(typeof(got) in [TYPE_ARRAY, TYPE_DICTIONARY]): - disp = str(result.summary, ' ', text) - - if(result.are_equal): - _fail(disp) - else: - _pass(disp) - - -# ------------------------------------------------------------------------------ -# Asserts that the expected value almost equals the value got. -# ------------------------------------------------------------------------------ -func assert_almost_eq(got, expected, error_interval, text=''): - var disp = "[" + _str(got) + "] expected to equal [" + _str(expected) + "] +/- [" + str(error_interval) + "]: " + text - if(_do_datatypes_match__fail_if_not(got, expected, text) and _do_datatypes_match__fail_if_not(got, error_interval, text)): - if not _is_almost_eq(got, expected, error_interval): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Asserts that the expected value does not almost equal the value got. -# ------------------------------------------------------------------------------ -func assert_almost_ne(got, not_expected, error_interval, text=''): - var disp = "[" + _str(got) + "] expected to not equal [" + _str(not_expected) + "] +/- [" + str(error_interval) + "]: " + text - if(_do_datatypes_match__fail_if_not(got, not_expected, text) and _do_datatypes_match__fail_if_not(got, error_interval, text)): - if _is_almost_eq(got, not_expected, error_interval): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Helper function which correctly compares two variables, -# while properly handling vector2/3 types -# ------------------------------------------------------------------------------ -func _is_almost_eq(got, expected, error_interval) -> bool: - var result = false - if typeof(got) == TYPE_VECTOR2: - if got.x >= (expected.x - error_interval.x) and got.x <= (expected.x + error_interval.x): - if got.y >= (expected.y - error_interval.y) and got.y <= (expected.y + error_interval.y): - result = true - elif typeof(got) == TYPE_VECTOR3: - if got.x >= (expected.x - error_interval.x) and got.x <= (expected.x + error_interval.x): - if got.y >= (expected.y - error_interval.y) and got.y <= (expected.y + error_interval.y): - if got.z >= (expected.z - error_interval.z) and got.z <= (expected.z + error_interval.z): - result = true - elif(got >= (expected - error_interval) and got <= (expected + error_interval)): - result = true - return(result) - -# ------------------------------------------------------------------------------ -# Asserts got is greater than expected -# ------------------------------------------------------------------------------ -func assert_gt(got, expected, text=""): - var disp = "[" + _str(got) + "] expected to be > than [" + _str(expected) + "]: " + text - if(_do_datatypes_match__fail_if_not(got, expected, text)): - if(got > expected): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts got is less than expected -# ------------------------------------------------------------------------------ -func assert_lt(got, expected, text=""): - var disp = "[" + _str(got) + "] expected to be < than [" + _str(expected) + "]: " + text - if(_do_datatypes_match__fail_if_not(got, expected, text)): - if(got < expected): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# asserts that got is true -# ------------------------------------------------------------------------------ -func assert_true(got, text=""): - if(typeof(got) == TYPE_BOOL): - if(got): - _pass(text) - else: - _fail(text) - else: - var msg = str("Cannot convert ", _strutils.type2str(got), " to boolean") - _fail(msg) - -# ------------------------------------------------------------------------------ -# Asserts that got is false -# ------------------------------------------------------------------------------ -func assert_false(got, text=""): - if(typeof(got) == TYPE_BOOL): - if(got): - _fail(text) - else: - _pass(text) - else: - var msg = str("Cannot convert ", _strutils.type2str(got), " to boolean") - _fail(msg) - -# ------------------------------------------------------------------------------ -# Asserts value is between (inclusive) the two expected values. -# ------------------------------------------------------------------------------ -func assert_between(got, expect_low, expect_high, text=""): - var disp = "[" + _str(got) + "] expected to be between [" + _str(expect_low) + "] and [" + str(expect_high) + "]: " + text - - if(_do_datatypes_match__fail_if_not(got, expect_low, text) and _do_datatypes_match__fail_if_not(got, expect_high, text)): - if(expect_low > expect_high): - disp = "INVALID range. [" + str(expect_low) + "] is not less than [" + str(expect_high) + "]" - _fail(disp) - else: - if(got < expect_low or got > expect_high): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Asserts value is not between (exclusive) the two expected values. -# ------------------------------------------------------------------------------ -func assert_not_between(got, expect_low, expect_high, text=""): - var disp = "[" + _str(got) + "] expected not to be between [" + _str(expect_low) + "] and [" + str(expect_high) + "]: " + text - - if(_do_datatypes_match__fail_if_not(got, expect_low, text) and _do_datatypes_match__fail_if_not(got, expect_high, text)): - if(expect_low > expect_high): - disp = "INVALID range. [" + str(expect_low) + "] is not less than [" + str(expect_high) + "]" - _fail(disp) - else: - if(got > expect_low and got < expect_high): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Uses the 'has' method of the object passed in to determine if it contains -# the passed in element. -# ------------------------------------------------------------------------------ -func assert_has(obj, element, text=""): - var disp = str('Expected [', _str(obj), '] to contain value: [', _str(element), ']: ', text) - if(obj.has(element)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func assert_does_not_have(obj, element, text=""): - var disp = str('Expected [', _str(obj), '] to NOT contain value: [', _str(element), ']: ', text) - if(obj.has(element)): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Asserts that a file exists -# ------------------------------------------------------------------------------ -func assert_file_exists(file_path): - var disp = 'expected [' + file_path + '] to exist.' - var f = File.new() - if(f.file_exists(file_path)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts that a file should not exist -# ------------------------------------------------------------------------------ -func assert_file_does_not_exist(file_path): - var disp = 'expected [' + file_path + '] to NOT exist' - var f = File.new() - if(!f.file_exists(file_path)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts the specified file is empty -# ------------------------------------------------------------------------------ -func assert_file_empty(file_path): - var disp = 'expected [' + file_path + '] to be empty' - var f = File.new() - if(f.file_exists(file_path) and gut.is_file_empty(file_path)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts the specified file is not empty -# ------------------------------------------------------------------------------ -func assert_file_not_empty(file_path): - var disp = 'expected [' + file_path + '] to contain data' - if(!gut.is_file_empty(file_path)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts the object has the specified method -# ------------------------------------------------------------------------------ -func assert_has_method(obj, method, text=''): - var disp = _str(obj) + ' should have method: ' + method - if(text != ''): - disp = _str(obj) + ' ' + text - assert_true(obj.has_method(method), disp) - -# Old deprecated method name -func assert_get_set_methods(obj, property, default, set_to): - _lgr.deprecated('assert_get_set_methods', 'assert_accessors') - assert_accessors(obj, property, default, set_to) - -# ------------------------------------------------------------------------------ -# Verifies the object has get and set methods for the property passed in. The -# property isn't tied to anything, just a name to be appended to the end of -# get_ and set_. Asserts the get_ and set_ methods exist, if not, it stops there. -# If they exist then it asserts get_ returns the expected default then calls -# set_ and asserts get_ has the value it was set to. -# ------------------------------------------------------------------------------ -func assert_accessors(obj, property, default, set_to): - var fail_count = _summary.failed - var get_func = 'get_' + property - var set_func = 'set_' + property - - if(obj.has_method('is_' + property)): - get_func = 'is_' + property - - assert_has_method(obj, get_func, 'should have getter starting with get_ or is_') - assert_has_method(obj, set_func) - # SHORT CIRCUIT - if(_summary.failed > fail_count): - return - assert_eq(obj.call(get_func), default, 'It should have the expected default value.') - obj.call(set_func, set_to) - assert_eq(obj.call(get_func), set_to, 'The set value should have been returned.') - - -# --------------------------------------------------------------------------- -# Property search helper. Used to retrieve Dictionary of specified property -# from passed object. Returns null if not found. -# If provided, property_usage constrains the type of property returned by -# passing either: -# EDITOR_PROPERTY for properties defined as: export(int) var some_value -# VARIABLE_PROPERTY for properties defined as: var another_value -# --------------------------------------------------------------------------- -func _find_object_property(obj, property_name, property_usage=null): - var result = null - var found = false - var properties = obj.get_property_list() - - while !found and !properties.empty(): - var property = properties.pop_back() - if property['name'] == property_name: - if property_usage == null or property['usage'] == property_usage: - result = property - found = true - return result - -# ------------------------------------------------------------------------------ -# Asserts a class exports a variable. -# ------------------------------------------------------------------------------ -func assert_exports(obj, property_name, type): - var disp = 'expected %s to have editor property [%s]' % [_str(obj), property_name] - var property = _find_object_property(obj, property_name, EDITOR_PROPERTY) - if property != null: - disp += ' of type [%s]. Got type [%s].' % [_strutils.types[type], _strutils.types[property['type']]] - if property['type'] == type: - _pass(disp) - else: - _fail(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Signal assertion helper. -# -# Verifies that the object and signal are valid for making signal assertions. -# This will fail with specific messages that indicate why they are not valid. -# This returns true/false to indicate if the object and signal are valid. -# ------------------------------------------------------------------------------ -func _can_make_signal_assertions(object, signal_name): - return !(_fail_if_not_watching(object) or _fail_if_does_not_have_signal(object, signal_name)) - -# ------------------------------------------------------------------------------ -# Check if an object is connected to a signal on another object. Returns True -# if it is and false otherwise -# ------------------------------------------------------------------------------ -func _is_connected(signaler_obj, connect_to_obj, signal_name, method_name=""): - if(method_name != ""): - return signaler_obj.is_connected(signal_name, connect_to_obj, method_name) - else: - var connections = signaler_obj.get_signal_connection_list(signal_name) - for conn in connections: - if((conn.source == signaler_obj) and (conn.target == connect_to_obj)): - return true - return false -# ------------------------------------------------------------------------------ -# Watch the signals for an object. This must be called before you can make -# any assertions about the signals themselves. -# ------------------------------------------------------------------------------ -func watch_signals(object): - _signal_watcher.watch_signals(object) - -# ------------------------------------------------------------------------------ -# Asserts that an object is connected to a signal on another object -# -# This will fail with specific messages if the target object is not connected -# to the specified signal on the source object. -# ------------------------------------------------------------------------------ -func assert_connected(signaler_obj, connect_to_obj, signal_name, method_name=""): - pass - var method_disp = '' - if (method_name != ""): - method_disp = str(' using method: [', method_name, '] ') - var disp = str('Expected object ', _str(signaler_obj),\ - ' to be connected to signal: [', signal_name, '] on ',\ - _str(connect_to_obj), method_disp) - if(_is_connected(signaler_obj, connect_to_obj, signal_name, method_name)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts that an object is not connected to a signal on another object -# -# This will fail with specific messages if the target object is connected -# to the specified signal on the source object. -# ------------------------------------------------------------------------------ -func assert_not_connected(signaler_obj, connect_to_obj, signal_name, method_name=""): - var method_disp = '' - if (method_name != ""): - method_disp = str(' using method: [', method_name, '] ') - var disp = str('Expected object ', _str(signaler_obj),\ - ' to not be connected to signal: [', signal_name, '] on ',\ - _str(connect_to_obj), method_disp) - if(_is_connected(signaler_obj, connect_to_obj, signal_name, method_name)): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Asserts that a signal has been emitted at least once. -# -# This will fail with specific messages if the object is not being watched or -# the object does not have the specified signal -# ------------------------------------------------------------------------------ -func assert_signal_emitted(object, signal_name, text=""): - var disp = str('Expected object ', _str(object), ' to have emitted signal [', signal_name, ']: ', text) - if(_can_make_signal_assertions(object, signal_name)): - if(_signal_watcher.did_emit(object, signal_name)): - _pass(disp) - else: - _fail(_get_fail_msg_including_emitted_signals(disp, object)) - -# ------------------------------------------------------------------------------ -# Asserts that a signal has not been emitted. -# -# This will fail with specific messages if the object is not being watched or -# the object does not have the specified signal -# ------------------------------------------------------------------------------ -func assert_signal_not_emitted(object, signal_name, text=""): - var disp = str('Expected object ', _str(object), ' to NOT emit signal [', signal_name, ']: ', text) - if(_can_make_signal_assertions(object, signal_name)): - if(_signal_watcher.did_emit(object, signal_name)): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Asserts that a signal was fired with the specified parameters. The expected -# parameters should be passed in as an array. An optional index can be passed -# when a signal has fired more than once. The default is to retrieve the most -# recent emission of the signal. -# -# This will fail with specific messages if the object is not being watched or -# the object does not have the specified signal -# ------------------------------------------------------------------------------ -func assert_signal_emitted_with_parameters(object, signal_name, parameters, index=-1): - if(typeof(parameters) != TYPE_ARRAY): - _lgr.error("The expected parameters must be wrapped in an array, you passed: " + _str(parameters)) - _fail("Bad Parameters") - return - - var disp = str('Expected object ', _str(object), ' to emit signal [', signal_name, '] with parameters ', parameters, ', got ') - if(_can_make_signal_assertions(object, signal_name)): - if(_signal_watcher.did_emit(object, signal_name)): - var parms_got = _signal_watcher.get_signal_parameters(object, signal_name, index) - var diff_result = _compare.deep(parameters, parms_got) - if(diff_result.are_equal()): - _pass(str(disp, parms_got)) - else: - _fail(str('Expected object ', _str(object), ' to emit signal [', signal_name, '] with parameters ', diff_result.summarize())) - else: - var text = str('Object ', object, ' did not emit signal [', signal_name, ']') - _fail(_get_fail_msg_including_emitted_signals(text, object)) - -# ------------------------------------------------------------------------------ -# Assert that a signal has been emitted a specific number of times. -# -# This will fail with specific messages if the object is not being watched or -# the object does not have the specified signal -# ------------------------------------------------------------------------------ -func assert_signal_emit_count(object, signal_name, times, text=""): - if(_can_make_signal_assertions(object, signal_name)): - var count = _signal_watcher.get_emit_count(object, signal_name) - var disp = str('Expected the signal [', signal_name, '] emit count of [', count, '] to equal [', times, ']: ', text) - if(count== times): - _pass(disp) - else: - _fail(_get_fail_msg_including_emitted_signals(disp, object)) - -# ------------------------------------------------------------------------------ -# Assert that the passed in object has the specified signal -# ------------------------------------------------------------------------------ -func assert_has_signal(object, signal_name, text=""): - var disp = str('Expected object ', _str(object), ' to have signal [', signal_name, ']: ', text) - if(_signal_watcher.does_object_have_signal(object, signal_name)): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Returns the number of times a signal was emitted. -1 returned if the object -# is not being watched. -# ------------------------------------------------------------------------------ -func get_signal_emit_count(object, signal_name): - return _signal_watcher.get_emit_count(object, signal_name) - -# ------------------------------------------------------------------------------ -# Get the parmaters of a fired signal. If the signal was not fired null is -# returned. You can specify an optional index (use get_signal_emit_count to -# determine the number of times it was emitted). The default index is the -# latest time the signal was fired (size() -1 insetead of 0). The parameters -# returned are in an array. -# ------------------------------------------------------------------------------ -func get_signal_parameters(object, signal_name, index=-1): - return _signal_watcher.get_signal_parameters(object, signal_name, index) - -# ------------------------------------------------------------------------------ -# Get the parameters for a method call to a doubled object. By default it will -# return the most recent call. You can optionally specify an index. -# -# Returns: -# * an array of parameter values if a call the method was found -# * null when a call to the method was not found or the index specified was -# invalid. -# ------------------------------------------------------------------------------ -func get_call_parameters(object, method_name, index=-1): - var to_return = null - if(_utils.is_double(object)): - to_return = gut.get_spy().get_call_parameters(object, method_name, index) - else: - _lgr.error('You must pass a doulbed object to get_call_parameters.') - - return to_return - -# ------------------------------------------------------------------------------ -# Returns the call count for a method with optional paramter matching. -# ------------------------------------------------------------------------------ -func get_call_count(object, method_name, parameters=null): - return gut.get_spy().call_count(object, method_name, parameters) - -# ------------------------------------------------------------------------------ -# Deprecated. Use assert_is. -# ------------------------------------------------------------------------------ -func assert_extends(object, a_class, text=''): - _lgr.deprecated('assert_extends', 'assert_is') - assert_is(object, a_class, text) - -# ------------------------------------------------------------------------------ -# Assert that object is an instance of a_class -# ------------------------------------------------------------------------------ -func assert_is(object, a_class, text=''): - var disp = ''#var disp = str('Expected [', _str(object), '] to be type of [', a_class, ']: ', text) - var NATIVE_CLASS = 'GDScriptNativeClass' - var GDSCRIPT_CLASS = 'GDScript' - var bad_param_2 = 'Parameter 2 must be a Class (like Node2D or Label). You passed ' - - if(typeof(object) != TYPE_OBJECT): - _fail(str('Parameter 1 must be an instance of an object. You passed: ', _str(object))) - elif(typeof(a_class) != TYPE_OBJECT): - _fail(str(bad_param_2, _str(a_class))) - else: - var a_str = _str(a_class) - disp = str('Expected [', _str(object), '] to extend [', a_str, ']: ', text) - if(a_class.get_class() != NATIVE_CLASS and a_class.get_class() != GDSCRIPT_CLASS): - _fail(str(bad_param_2, a_str)) - else: - if(object is a_class): - _pass(disp) - else: - _fail(disp) - -func _get_typeof_string(the_type): - var to_return = "" - if(_strutils.types.has(the_type)): - to_return += str(the_type, '(', _strutils.types[the_type], ')') - else: - to_return += str(the_type) - return to_return - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func assert_typeof(object, type, text=''): - var disp = str('Expected [typeof(', object, ') = ') - disp += _get_typeof_string(typeof(object)) - disp += '] to equal [' - disp += _get_typeof_string(type) + ']' - disp += '. ' + text - if(typeof(object) == type): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func assert_not_typeof(object, type, text=''): - var disp = str('Expected [typeof(', object, ') = ') - disp += _get_typeof_string(typeof(object)) - disp += '] to not equal [' - disp += _get_typeof_string(type) + ']' - disp += '. ' + text - if(typeof(object) != type): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Assert that text contains given search string. -# The match_case flag determines case sensitivity. -# ------------------------------------------------------------------------------ -func assert_string_contains(text, search, match_case=true): - var empty_search = 'Expected text and search strings to be non-empty. You passed \'%s\' and \'%s\'.' - var disp = 'Expected \'%s\' to contain \'%s\', match_case=%s' % [text, search, match_case] - if(text == '' or search == ''): - _fail(empty_search % [text, search]) - elif(match_case): - if(text.find(search) == -1): - _fail(disp) - else: - _pass(disp) - else: - if(text.to_lower().find(search.to_lower()) == -1): - _fail(disp) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Assert that text starts with given search string. -# match_case flag determines case sensitivity. -# ------------------------------------------------------------------------------ -func assert_string_starts_with(text, search, match_case=true): - var empty_search = 'Expected text and search strings to be non-empty. You passed \'%s\' and \'%s\'.' - var disp = 'Expected \'%s\' to start with \'%s\', match_case=%s' % [text, search, match_case] - if(text == '' or search == ''): - _fail(empty_search % [text, search]) - elif(match_case): - if(text.find(search) == 0): - _pass(disp) - else: - _fail(disp) - else: - if(text.to_lower().find(search.to_lower()) == 0): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Assert that text ends with given search string. -# match_case flag determines case sensitivity. -# ------------------------------------------------------------------------------ -func assert_string_ends_with(text, search, match_case=true): - var empty_search = 'Expected text and search strings to be non-empty. You passed \'%s\' and \'%s\'.' - var disp = 'Expected \'%s\' to end with \'%s\', match_case=%s' % [text, search, match_case] - var required_index = len(text) - len(search) - if(text == '' or search == ''): - _fail(empty_search % [text, search]) - elif(match_case): - if(text.find(search) == required_index): - _pass(disp) - else: - _fail(disp) - else: - if(text.to_lower().find(search.to_lower()) == required_index): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Assert that a method was called on an instance of a doubled class. If -# parameters are supplied then the params passed in when called must match. -# TODO make 3rd parameter "param_or_text" and add fourth parameter of "text" and -# then work some magic so this can have a "text" parameter without being -# annoying. -# ------------------------------------------------------------------------------ -func assert_called(inst, method_name, parameters=null): - var disp = str('Expected [',method_name,'] to have been called on ',_str(inst)) - - if(_fail_if_parameters_not_array(parameters)): - return - - if(!_utils.is_double(inst)): - _fail('You must pass a doubled instance to assert_called. Check the wiki for info on using double.') - else: - if(gut.get_spy().was_called(inst, method_name, parameters)): - _pass(disp) - else: - if(parameters != null): - disp += str(' with parameters ', parameters) - _fail(str(disp, "\n", _get_desc_of_calls_to_instance(inst))) - -# ------------------------------------------------------------------------------ -# Assert that a method was not called on an instance of a doubled class. If -# parameters are specified then this will only fail if it finds a call that was -# sent matching parameters. -# ------------------------------------------------------------------------------ -func assert_not_called(inst, method_name, parameters=null): - var disp = str('Expected [', method_name, '] to NOT have been called on ', _str(inst)) - - if(_fail_if_parameters_not_array(parameters)): - return - - if(!_utils.is_double(inst)): - _fail('You must pass a doubled instance to assert_not_called. Check the wiki for info on using double.') - else: - if(gut.get_spy().was_called(inst, method_name, parameters)): - if(parameters != null): - disp += str(' with parameters ', parameters) - _fail(str(disp, "\n", _get_desc_of_calls_to_instance(inst))) - else: - _pass(disp) - -# ------------------------------------------------------------------------------ -# Assert that a method on an instance of a doubled class was called a number -# of times. If parameters are specified then only calls with matching -# parameter values will be counted. -# ------------------------------------------------------------------------------ -func assert_call_count(inst, method_name, expected_count, parameters=null): - var count = gut.get_spy().call_count(inst, method_name, parameters) - - if(_fail_if_parameters_not_array(parameters)): - return - - var param_text = '' - if(parameters): - param_text = ' with parameters ' + str(parameters) - var disp = 'Expected [%s] on %s to be called [%s] times%s. It was called [%s] times.' - disp = disp % [method_name, _str(inst), expected_count, param_text, count] - - if(!_utils.is_double(inst)): - _fail('You must pass a doubled instance to assert_call_count. Check the wiki for info on using double.') - else: - if(count == expected_count): - _pass(disp) - else: - _fail(str(disp, "\n", _get_desc_of_calls_to_instance(inst))) - -# ------------------------------------------------------------------------------ -# Asserts the passed in value is null -# ------------------------------------------------------------------------------ -func assert_null(got, text=''): - var disp = str('Expected [', _str(got), '] to be NULL: ', text) - if(got == null): - _pass(disp) - else: - _fail(disp) - -# ------------------------------------------------------------------------------ -# Asserts the passed in value is null -# ------------------------------------------------------------------------------ -func assert_not_null(got, text=''): - var disp = str('Expected [', _str(got), '] to be anything but NULL: ', text) - if(got == null): - _fail(disp) - else: - _pass(disp) - -# ----------------------------------------------------------------------------- -# Asserts object has been freed from memory -# We pass in a title (since if it is freed, we lost all identity data) -# ----------------------------------------------------------------------------- -func assert_freed(obj, title='something'): - var disp = title - if(is_instance_valid(obj)): - disp = _strutils.type2str(obj) + title - assert_true(not is_instance_valid(obj), "Expected [%s] to be freed" % disp) - -# ------------------------------------------------------------------------------ -# Asserts Object has not been freed from memory -# ----------------------------------------------------------------------------- -func assert_not_freed(obj, title): - var disp = title - if(is_instance_valid(obj)): - disp = _strutils.type2str(obj) + title - assert_true(is_instance_valid(obj), "Expected [%s] to not be freed" % disp) - -# ------------------------------------------------------------------------------ -# Asserts that the current test has not introduced any new orphans. This only -# applies to the test code that preceedes a call to this method so it should be -# the last thing your test does. -# ------------------------------------------------------------------------------ -func assert_no_new_orphans(text=''): - var count = gut.get_orphan_counter().get_counter('test') - var msg = '' - if(text != ''): - msg = ': ' + text - # Note that get_counter will return -1 if the counter does not exist. This - # can happen with a misplaced assert_no_new_orphans. Checking for > 0 - # ensures this will not cause some weird failure. - if(count > 0): - _fail(str('Expected no orphans, but found ', count, msg)) - else: - _pass('No new orphans found.' + msg) - -# ------------------------------------------------------------------------------ -# Returns a dictionary that contains -# - an is_valid flag whether validation was successful or not and -# - a message that gives some information about the validation errors. -# ------------------------------------------------------------------------------ -func _validate_assert_setget_called_input(type, name_property - , name_setter, name_getter): - var obj = null - var result = {"is_valid": true, "msg": ""} - - if null == type or typeof(type) != TYPE_OBJECT or not type.is_class("Resource"): - result.is_valid = false - result.msg = str("The type parameter should be a ressource, ", _str(type), ' was passed.') - return result - - if null == double(type): - result.is_valid = false - result.msg = str("Attempt to double the type parameter failed. The type parameter should be a ressource that can be doubled.") - return result - - obj = _create_obj_from_type(type) - var property = _find_object_property(obj, str(name_property)) - - if null == property: - result.is_valid = false - result.msg += str("The property %s does not exist." % _str(name_property)) - if name_setter == "" and name_getter == "": - result.is_valid = false - result.msg += str("Either setter or getter method must be specified.") - if name_setter != "" and not obj.has_method(str(name_setter)): - result.is_valid = false - result.msg += str("Setter method %s does not exist. " % _str(name_setter)) - if name_getter != "" and not obj.has_method(str(name_getter)): - result.is_valid = false - result.msg += str("Getter method %s does not exist. " %_str(name_getter)) - - obj.free() - return result - -# ------------------------------------------------------------------------------ -# Validates the singleton_name is a string and exists. Errors when conditions -# are not met. Returns true/false if singleton_name is valid or not. -# ------------------------------------------------------------------------------ -func _validate_singleton_name(singleton_name): - var is_valid = true - if(typeof(singleton_name) != TYPE_STRING): - _lgr.error("double_singleton requires a Godot singleton name, you passed " + _str(singleton_name)) - is_valid = false - # Sometimes they have underscores in front of them, sometimes they do not. - # The doubler is smart enought of ind the right thing, so this has to be - # that smart as well. - elif(!ClassDB.class_exists(singleton_name) and !ClassDB.class_exists('_' + singleton_name)): - var txt = str("The singleton [", singleton_name, "] could not be found. ", - "Check the GlobalScope page for a list of singletons.") - _lgr.error(txt) - is_valid = false - return is_valid - - -# ------------------------------------------------------------------------------ -# Asserts the given setter and getter methods are called when the given property -# is accessed. -# ------------------------------------------------------------------------------ -func _assert_setget_called(type, name_property, setter = "", getter = ""): - var name_setter = _utils.nvl(setter, "") - var name_getter = _utils.nvl(getter, "") - - var validation = _validate_assert_setget_called_input(type, name_property, str(name_setter), str(name_getter)) - if not validation.is_valid: - _fail(validation.msg) - return - - var message = "" - var amount_calls_setter = 0 - var amount_calls_getter = 0 - var expected_calls_setter = 0 - var expected_calls_getter = 0 - var obj = _create_obj_from_type(double(type)) - - if name_setter != '': - expected_calls_setter = 1 - stub(obj, name_setter).to_do_nothing() - obj.set(name_property, null) - amount_calls_setter = gut.get_spy().call_count(obj, str(name_setter)) - - if name_getter != '': - expected_calls_getter = 1 - stub(obj, name_getter).to_do_nothing() - var __new_property = obj.get(name_property) - amount_calls_getter = gut.get_spy().call_count(obj, str(name_getter)) - - obj.free() - - # assert - - if amount_calls_setter == expected_calls_setter and amount_calls_getter == expected_calls_getter: - _pass(str("setget for %s is correctly configured." % _str(name_property))) - else: - if amount_calls_setter < expected_calls_setter: - message += " The setter was not called." - elif amount_calls_setter > expected_calls_setter: - message += " The setter was called but should not have been." - if amount_calls_getter < expected_calls_getter: - message += " The getter was not called." - elif amount_calls_getter > expected_calls_getter: - message += " The getter was called but should not have been." - _fail(str(message)) - -# ------------------------------------------------------------------------------ -# Wrapper: invokes assert_setget_called but provides a slightly more convenient -# signature -# ------------------------------------------------------------------------------ -func assert_setget( - instance, name_property, - const_or_setter = DEFAULT_SETTER_GETTER, getter="__not_set__"): - - var getter_name = null - if(getter != "__not_set__"): - getter_name = getter - - var setter_name = null - if(typeof(const_or_setter) == TYPE_INT): - if(const_or_setter in [SETTER_ONLY, DEFAULT_SETTER_GETTER]): - setter_name = str("set_", name_property) - - if(const_or_setter in [GETTER_ONLY, DEFAULT_SETTER_GETTER]): - getter_name = str("get_", name_property) - else: - setter_name = const_or_setter - - var resource = null - if instance.is_class("Resource"): - resource = instance - else: - resource = instance.get_script() - - _assert_setget_called(resource, str(name_property), setter_name, getter_name) - - -# ------------------------------------------------------------------------------ -# Wrapper: asserts if the property exists, the accessor methods exist and the -# setget keyword is set for accessor methods -# ------------------------------------------------------------------------------ -func assert_property(instance, name_property, default_value, new_value) -> void: - var free_me = [] - var resource = null - var obj = null - if instance.is_class("Resource"): - resource = instance - obj = _create_obj_from_type(resource) - free_me.append(obj) - else: - resource = instance.get_script() - obj = instance - - var name_setter = "set_" + str(name_property) - var name_getter = "get_" + str(name_property) - - var pre_fail_count = get_fail_count() - assert_accessors(obj, str(name_property), default_value, new_value) - _assert_setget_called(resource, str(name_property), name_setter, name_getter) - - for entry in free_me: - entry.free() - - # assert - if get_fail_count() == pre_fail_count: - _pass(str("The property is set up as expected.")) - else: - _fail(str("The property is not set up as expected. Examine subtests to see what failed.")) - - -# ------------------------------------------------------------------------------ -# Mark the current test as pending. -# ------------------------------------------------------------------------------ -func pending(text=""): - _summary.pending += 1 - if(gut): - _lgr.pending(text) - gut._pending(text) - -# ------------------------------------------------------------------------------ -# Returns the number of times a signal was emitted. -1 returned if the object -# is not being watched. -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# Yield for the time sent in. The optional message will be printed when -# Gut detects the yield. When the time expires the YIELD signal will be -# emitted. -# ------------------------------------------------------------------------------ -func yield_for(time, msg=''): - return gut.set_yield_time(time, msg) - -# ------------------------------------------------------------------------------ -# Yield to a signal or a maximum amount of time, whichever comes first. When -# the conditions are met the YIELD signal will be emitted. -# ------------------------------------------------------------------------------ -func yield_to(obj, signal_name, max_wait, msg=''): - watch_signals(obj) - gut.set_yield_signal_or_time(obj, signal_name, max_wait, msg) - - return gut - -# ------------------------------------------------------------------------------ -# Yield for a number of frames. The optional message will be printed. when -# Gut detects a yield. When the number of frames have elapsed (counted in gut's -# _process function) the YIELD signal will be emitted. -# ------------------------------------------------------------------------------ -func yield_frames(frames, msg=''): - if(frames <= 0): - var text = str('yeild_frames: frames must be > 0, you passed ', frames, '. 0 frames waited.') - _lgr.error(text) - frames = 0 - - gut.set_yield_frames(frames, msg) - return gut - -# ------------------------------------------------------------------------------ -# Ends a test that had a yield in it. You only need to use this if you do -# not make assertions after a yield. -# ------------------------------------------------------------------------------ -func end_test(): - _lgr.deprecated('end_test is no longer necessary, you can remove it.') - #gut.end_yielded_test() - -func get_summary(): - return _summary - -func get_fail_count(): - return _summary.failed - -func get_pass_count(): - return _summary.passed - -func get_pending_count(): - return _summary.pending - -func get_assert_count(): - return _summary.asserts - -func clear_signal_watcher(): - _signal_watcher.clear() - -func get_double_strategy(): - return gut.get_doubler().get_strategy() - -func set_double_strategy(double_strategy): - gut.get_doubler().set_strategy(double_strategy) - -func pause_before_teardown(): - gut.pause_before_teardown() - -# ------------------------------------------------------------------------------ -# Convert the _summary dictionary into text -# ------------------------------------------------------------------------------ -func get_summary_text(): - var to_return = get_script().get_path() + "\n" - to_return += str(' ', _summary.passed, ' of ', _summary.asserts, ' passed.') - if(_summary.pending > 0): - to_return += str("\n ", _summary.pending, ' pending') - if(_summary.failed > 0): - to_return += str("\n ", _summary.failed, ' failed.') - return to_return - -# ------------------------------------------------------------------------------ -# Double a script, inner class, or scene using a path or a loaded script/scene. -# -# -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func _smart_double(double_info): - var override_strat = _utils.nvl(double_info.strategy, gut.get_doubler().get_strategy()) - var to_return = null - - if(double_info.is_scene()): - if(double_info.make_partial): - to_return = gut.get_doubler().partial_double_scene(double_info.path, override_strat) - else: - to_return = gut.get_doubler().double_scene(double_info.path, override_strat) - - elif(double_info.is_native()): - if(double_info.make_partial): - to_return = gut.get_doubler().partial_double_gdnative(double_info.path) - else: - to_return = gut.get_doubler().double_gdnative(double_info.path) - - elif(double_info.is_script()): - if(double_info.subpath == null): - if(double_info.make_partial): - to_return = gut.get_doubler().partial_double(double_info.path, override_strat) - else: - to_return = gut.get_doubler().double(double_info.path, override_strat) - else: - if(double_info.make_partial): - to_return = gut.get_doubler().partial_double_inner(double_info.path, double_info.subpath, override_strat) - else: - to_return = gut.get_doubler().double_inner(double_info.path, double_info.subpath, override_strat) - return to_return - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func double(thing, p2=null, p3=null): - var double_info = DoubleInfo.new(thing, p2, p3) - if(!double_info.is_valid): - _lgr.error('double requires a class or path, you passed an instance: ' + _str(thing)) - return null - - double_info.make_partial = false - - return _smart_double(double_info) - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -func partial_double(thing, p2=null, p3=null): - var double_info = DoubleInfo.new(thing, p2, p3) - if(!double_info.is_valid): - _lgr.error('partial_double requires a class or path, you passed an instance: ' + _str(thing)) - return null - - double_info.make_partial = true - - return _smart_double(double_info) - -# ------------------------------------------------------------------------------ -# Doubles a Godot singleton -# ------------------------------------------------------------------------------ -func double_singleton(singleton_name): - return null - # var to_return = null - # if(_validate_singleton_name(singleton_name)): - # to_return = gut.get_doubler().double_singleton(singleton_name) - # return to_return - -# ------------------------------------------------------------------------------ -# Partial Doubles a Godot singleton -# ------------------------------------------------------------------------------ -func partial_double_singleton(singleton_name): - return null - # var to_return = null - # if(_validate_singleton_name(singleton_name)): - # to_return = gut.get_doubler().partial_double_singleton(singleton_name) - # return to_return - -# ------------------------------------------------------------------------------ -# Specifically double a scene -# ------------------------------------------------------------------------------ -func double_scene(path, strategy=null): - var override_strat = _utils.nvl(strategy, gut.get_doubler().get_strategy()) - return gut.get_doubler().double_scene(path, override_strat) - -# ------------------------------------------------------------------------------ -# Specifically double a script -# ------------------------------------------------------------------------------ -func double_script(path, strategy=null): - var override_strat = _utils.nvl(strategy, gut.get_doubler().get_strategy()) - return gut.get_doubler().double(path, override_strat) - -# ------------------------------------------------------------------------------ -# Specifically double an Inner class in a a script -# ------------------------------------------------------------------------------ -func double_inner(path, subpath, strategy=null): - var override_strat = _utils.nvl(strategy, gut.get_doubler().get_strategy()) - return gut.get_doubler().double_inner(path, subpath, override_strat) - - -# ------------------------------------------------------------------------------ -# Add a method that the doubler will ignore. You can pass this the path to a -# script or scene or a loaded script or scene. When running tests, these -# ignores are cleared after every test. -# ------------------------------------------------------------------------------ -func ignore_method_when_doubling(thing, method_name): - var double_info = DoubleInfo.new(thing) - var path = double_info.path - - if(double_info.is_scene()): - var inst = thing.instance() - if(inst.get_script()): - path = inst.get_script().get_path() - - gut.get_doubler().add_ignored_method(path, method_name) - -# ------------------------------------------------------------------------------ -# Stub something. -# -# Parameters -# 1: the thing to stub, a file path or a instance or a class -# 2: either an inner class subpath or the method name -# 3: the method name if an inner class subpath was specified -# NOTE: right now we cannot stub inner classes at the path level so this should -# only be called with two parameters. I did the work though so I'm going -# to leave it but not update the wiki. -# ------------------------------------------------------------------------------ -func stub(thing, p2, p3=null): - if(_utils.is_instance(thing) and !_utils.is_double(thing)): - _lgr.error(str('You cannot use stub on ', _str(thing), ' because it is not a double.')) - return _utils.StubParams.new() - - var method_name = p2 - var subpath = null - if(p3 != null): - subpath = p2 - method_name = p3 - - var sp = _utils.StubParams.new(thing, method_name, subpath) - gut.get_stubber().add_stub(sp) - return sp - -# ------------------------------------------------------------------------------ -# convenience wrapper. -# ------------------------------------------------------------------------------ -func simulate(obj, times, delta): - gut.simulate(obj, times, delta) - -# ------------------------------------------------------------------------------ -# Replace the node at base_node.get_node(path) with with_this. All references -# to the node via $ and get_node(...) will now return with_this. with_this will -# get all the groups that the node that was replaced had. -# -# The node that was replaced is queued to be freed. -# -# TODO see replace_by method, this could simplify the logic here. -# ------------------------------------------------------------------------------ -func replace_node(base_node, path_or_node, with_this): - var path = path_or_node - - if(typeof(path_or_node) != TYPE_STRING): - # This will cause an engine error if it fails. It always returns a - # NodePath, even if it fails. Checking the name count is the only way - # I found to check if it found something or not (after it worked I - # didn't look any farther). - path = base_node.get_path_to(path_or_node) - if(path.get_name_count() == 0): - _lgr.error('You passed an object that base_node does not have. Cannot replace node.') - return - - if(!base_node.has_node(path)): - _lgr.error(str('Could not find node at path [', path, ']')) - return - - var to_replace = base_node.get_node(path) - var parent = to_replace.get_parent() - var replace_name = to_replace.get_name() - - parent.remove_child(to_replace) - parent.add_child(with_this) - with_this.set_name(replace_name) - with_this.set_owner(parent) - - var groups = to_replace.get_groups() - for i in range(groups.size()): - with_this.add_to_group(groups[i]) - - to_replace.queue_free() - - -# ------------------------------------------------------------------------------ -# This method does a somewhat complicated dance with Gut. It assumes that Gut -# will clear its parameter handler after it finishes calling a parameterized test -# enough times. -# ------------------------------------------------------------------------------ -func use_parameters(params): - var ph = gut.get_parameter_handler() - if(ph == null): - ph = _utils.ParameterHandler.new(params) - gut.set_parameter_handler(ph) - - var output = str('(call #', ph.get_call_count() + 1, ') with parameters: ', ph.get_current_parameters()) - _lgr.log(output) - _lgr.inc_indent() - return ph.next_parameters() - -# ------------------------------------------------------------------------------ -# Marks whatever is passed in to be freed after the test finishes. It also -# returns what is passed in so you can save a line of code. -# var thing = autofree(Thing.new()) -# ------------------------------------------------------------------------------ -func autofree(thing): - gut.get_autofree().add_free(thing) - return thing - -# ------------------------------------------------------------------------------ -# Works the same as autofree except queue_free will be called on the object -# instead. This also imparts a brief pause after the test finishes so that -# the queued object has time to free. -# ------------------------------------------------------------------------------ -func autoqfree(thing): - gut.get_autofree().add_queue_free(thing) - return thing - -# ------------------------------------------------------------------------------ -# The same as autofree but it also adds the object as a child of the test. -# ------------------------------------------------------------------------------ -func add_child_autofree(node, legible_unique_name = false): - gut.get_autofree().add_free(node) - # Explicitly calling super here b/c add_child MIGHT change and I don't want - # a bug sneaking its way in here. - .add_child(node, legible_unique_name) - return node - -# ------------------------------------------------------------------------------ -# The same as autoqfree but it also adds the object as a child of the test. -# ------------------------------------------------------------------------------ -func add_child_autoqfree(node, legible_unique_name=false): - gut.get_autofree().add_queue_free(node) - # Explicitly calling super here b/c add_child MIGHT change and I don't want - # a bug sneaking its way in here. - .add_child(node, legible_unique_name) - return node - -# ------------------------------------------------------------------------------ -# Returns true if the test is passing as of the time of this call. False if not. -# ------------------------------------------------------------------------------ -func is_passing(): - if(gut.get_current_test_object() != null and - !['before_all', 'after_all'].has(gut.get_current_test_object().name)): - return gut.get_current_test_object().passed and \ - gut.get_current_test_object().assert_count > 0 - else: - _lgr.error('No current test object found. is_passing must be called inside a test.') - return null - -# ------------------------------------------------------------------------------ -# Returns true if the test is failing as of the time of this call. False if not. -# ------------------------------------------------------------------------------ -func is_failing(): - if(gut.get_current_test_object() != null and - !['before_all', 'after_all'].has(gut.get_current_test_object().name)): - return !gut.get_current_test_object().passed - else: - _lgr.error('No current test object found. is_failing must be called inside a test.') - return null - -# ------------------------------------------------------------------------------ -# Marks the test as passing. Does not override any failing asserts or calls to -# fail_test. Same as a passing assert. -# ------------------------------------------------------------------------------ -func pass_test(text): - _pass(text) - -# ------------------------------------------------------------------------------ -# Marks the test as failing. Same as a failing assert. -# ------------------------------------------------------------------------------ -func fail_test(text): - _fail(text) - -# ------------------------------------------------------------------------------ -# Peforms a deep compare on both values, a CompareResult instnace is returned. -# The optional max_differences paramter sets the max_differences to be displayed. -# ------------------------------------------------------------------------------ -func compare_deep(v1, v2, max_differences=null): - var result = _compare.deep(v1, v2) - if(max_differences != null): - result.max_differences = max_differences - return result - -# ------------------------------------------------------------------------------ -# Peforms a shallow compare on both values, a CompareResult instnace is returned. -# The optional max_differences paramter sets the max_differences to be displayed. -# ------------------------------------------------------------------------------ -func compare_shallow(v1, v2, max_differences=null): - var result = _compare.shallow(v1, v2) - if(max_differences != null): - result.max_differences = max_differences - return result - -# ------------------------------------------------------------------------------ -# Performs a deep compare and asserts the values are equal -# ------------------------------------------------------------------------------ -func assert_eq_deep(v1, v2): - var result = compare_deep(v1, v2) - if(result.are_equal): - _pass(result.get_short_summary()) - else: - _fail(result.summary) - -# ------------------------------------------------------------------------------ -# Performs a deep compare and asserts the values are not equal -# ------------------------------------------------------------------------------ -func assert_ne_deep(v1, v2): - var result = compare_deep(v1, v2) - if(!result.are_equal): - _pass(result.get_short_summary()) - else: - _fail(result.get_short_summary()) - -# ------------------------------------------------------------------------------ -# Performs a shallow compare and asserts the values are equal -# ------------------------------------------------------------------------------ -func assert_eq_shallow(v1, v2): - var result = compare_shallow(v1, v2) - if(result.are_equal): - _pass(result.get_short_summary()) - else: - _fail(result.summary) - -# ------------------------------------------------------------------------------ -# Performs a shallow compare and asserts the values are not equal -# ------------------------------------------------------------------------------ -func assert_ne_shallow(v1, v2): - var result = compare_shallow(v1, v2) - if(!result.are_equal): - _pass(result.get_short_summary()) - else: - _fail(result.get_short_summary()) - - -# ------------------------------------------------------------------------------ -# Checks the passed in version string (x.x.x) against the engine version to see -# if the engine version is less than the expected version. If it is then the -# test is mareked as passed (for a lack of anything better to do). The result -# of the check is returned. -# -# Example: -# if(skip_if_godot_version_lt('3.5.0')): -# return -# ------------------------------------------------------------------------------ -func skip_if_godot_version_lt(expected): - var should_skip = !_utils.is_godot_version_gte(expected) - if(should_skip): - _pass(str('Skipping ', _utils.godot_version(), ' is less than ', expected)) - return should_skip - - -# ------------------------------------------------------------------------------ -# Checks if the passed in version matches the engine version. The passed in -# version can contain just the major, major.minor or major.minor.path. If -# the version is not the same then the test is marked as passed. The result of -# the check is returned. -# -# Example: -# if(skip_if_godot_version_ne('3.4')): -# return -# ------------------------------------------------------------------------------ -func skip_if_godot_version_ne(expected): - var should_skip = !_utils.is_godot_version(expected) - if(should_skip): - _pass(str('Skipping ', _utils.godot_version(), ' is not ', expected)) - return should_skip
\ No newline at end of file |
