chore: release version 2.3.5 and refactor lobby
Bump export_presets.cfg version to 2.3.5. Update CHANGELOG_DRAFT.md. Refactor lobby.gd into LobbyChat, LobbyMainMenu, LobbyRoomList, LobbyRoom. Move Nakama config to environment variables in nakama_manager.gd. Derive auth_manager.gd encryption key from OS.get_unique_id().sha256_text(). Remove Steam email auth fallback. Require auth ticket. Make GachaManager.pull() async in gacha_panel.gd. Remove dummy wallet seeding. Add store_type to IAP payload. Validate IAP receipts server-side in economy.lua. Register gacha module in main.lua. Clean backend_service.gd stubs. Fix featured_banners type safety in gacha_manager.gd. Guards non-array responses. Move tiles_armagedon_a1.res to assets/models/meshes/. Fix import fallback_path.
This commit is contained in:
+1261
@@ -0,0 +1,1261 @@
|
||||
extends 'res://addons/gut/gut_to_move.gd'
|
||||
class_name GutMain
|
||||
## The GUT brains.
|
||||
##
|
||||
## Most of this class is for internal use only. Features that can be used are
|
||||
## have descriptions and can be accessed through the [member GutTest.gut] variable
|
||||
## in your test scripts (extends [GutTest]).
|
||||
## The wiki page for this class contains only the usable features.
|
||||
## [br][br]
|
||||
## GUT Wiki: [url=https://gut.readthedocs.io]https://gut.readthedocs.io[/url]
|
||||
## [br]
|
||||
## @ignore-uncommented
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# Constants
|
||||
# ---------------------------
|
||||
const LOG_LEVEL_FAIL_ONLY = 0
|
||||
const LOG_LEVEL_TEST_AND_FAILURES = 1
|
||||
const LOG_LEVEL_ALL_ASSERTS = 2
|
||||
const WAITING_MESSAGE = '/# waiting #/'
|
||||
const PAUSE_MESSAGE = '/# Pausing. Press continue button...#/'
|
||||
const COMPLETED = 'completed'
|
||||
|
||||
# ---------------------------
|
||||
# Signals
|
||||
# ---------------------------
|
||||
signal start_pause_before_teardown
|
||||
signal end_pause_before_teardown
|
||||
|
||||
signal start_run
|
||||
signal end_run
|
||||
signal start_script(test_script_obj)
|
||||
signal end_script
|
||||
signal start_test(test_name)
|
||||
signal end_test
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# Settings
|
||||
#
|
||||
# These are properties that are usually set before a run is started through
|
||||
# gutconfig.
|
||||
# ---------------------------
|
||||
|
||||
var _inner_class_name = ''
|
||||
# When set, GUT will only run Inner-Test-Classes that contain this string.
|
||||
var inner_class_name = _inner_class_name :
|
||||
get: return _inner_class_name
|
||||
set(val): _inner_class_name = val
|
||||
|
||||
var _ignore_pause_before_teardown = false
|
||||
# For batch processing purposes, you may want to ignore any calls to
|
||||
# pause_before_teardown that you forgot to remove_at.
|
||||
var ignore_pause_before_teardown = _ignore_pause_before_teardown :
|
||||
get: return _ignore_pause_before_teardown
|
||||
set(val): _ignore_pause_before_teardown = val
|
||||
|
||||
var _log_level = 1
|
||||
## The log detail level. Valid values are 0 - 2. Larger values do not matter.
|
||||
var log_level = _log_level:
|
||||
get: return _log_level
|
||||
set(val): _set_log_level(val)
|
||||
|
||||
## The amount of time that must elapse before an "Awaiting" message is printed.
|
||||
var wait_log_delay = 0.5
|
||||
|
||||
# TODO 4.0
|
||||
# This appears to not be used anymore. Going to wait for more tests to be
|
||||
# ported before removing.
|
||||
var _disable_strict_datatype_checks = false
|
||||
var disable_strict_datatype_checks = false :
|
||||
get: return _disable_strict_datatype_checks
|
||||
set(val): _disable_strict_datatype_checks = val
|
||||
|
||||
var _export_path = ''
|
||||
# Path to file that GUT will create which holds a list of all test scripts so
|
||||
# that GUT can run tests when a project is exported.
|
||||
var export_path = '' :
|
||||
get: return _export_path
|
||||
set(val): _export_path = val
|
||||
|
||||
var _include_subdirectories = false
|
||||
# Setting this to true will make GUT search all subdirectories of any directory
|
||||
# you have configured GUT to search for tests in.
|
||||
var include_subdirectories = _include_subdirectories :
|
||||
get: return _include_subdirectories
|
||||
set(val): _include_subdirectories = val
|
||||
|
||||
|
||||
var _double_strategy = GutUtils.DOUBLE_STRATEGY.SCRIPT_ONLY
|
||||
# TODO rework what this is and then document it here.
|
||||
var double_strategy = _double_strategy :
|
||||
get: return _double_strategy
|
||||
set(val):
|
||||
if(GutUtils.DOUBLE_STRATEGY.values().has(val)):
|
||||
_double_strategy = val
|
||||
_doubler.set_strategy(double_strategy)
|
||||
else:
|
||||
_lgr.error(str("gut.gd: invalid double_strategy ", val))
|
||||
|
||||
var _pre_run_script = ''
|
||||
# Path to the script that will be run before all tests are run. This script
|
||||
# must extend GutHookScript
|
||||
var pre_run_script = _pre_run_script :
|
||||
get: return _pre_run_script
|
||||
set(val): _pre_run_script = val
|
||||
|
||||
var _post_run_script = ''
|
||||
# Path to the script that will run after all tests have run. The script
|
||||
# must extend GutHookScript
|
||||
var post_run_script = _post_run_script :
|
||||
get: return _post_run_script
|
||||
set(val): _post_run_script = val
|
||||
|
||||
var _color_output = false
|
||||
# Flag to color output at the command line and in the GUT GUI.
|
||||
var color_output = false :
|
||||
get: return _color_output
|
||||
set(val):
|
||||
_color_output = val
|
||||
_lgr.disable_formatting(!_color_output)
|
||||
|
||||
var _junit_xml_file = ''
|
||||
# The full path to where GUT should write a JUnit compliant XML file to which
|
||||
# contains the results of all tests run.
|
||||
var junit_xml_file = '' :
|
||||
get: return _junit_xml_file
|
||||
set(val): _junit_xml_file = val
|
||||
|
||||
var _junit_xml_timestamp = false
|
||||
# When true and junit_xml_file is set, the file name will include a
|
||||
# timestamp so that previous files are not overwritten.
|
||||
var junit_xml_timestamp = false :
|
||||
get: return _junit_xml_timestamp
|
||||
set(val): _junit_xml_timestamp = val
|
||||
|
||||
# The minimum amout of time GUT will wait before pausing for 1 frame to allow
|
||||
# the screen to paint. GUT checkes after each test to see if enough time has
|
||||
# passed.
|
||||
var paint_after = .1:
|
||||
get: return paint_after
|
||||
set(val): paint_after = val
|
||||
|
||||
var _unit_test_name = ''
|
||||
# When set GUT will only run tests that contain this string.
|
||||
var unit_test_name = _unit_test_name :
|
||||
get: return _unit_test_name
|
||||
set(val): _unit_test_name = val
|
||||
|
||||
var _parameter_handler = null
|
||||
# This is populated by test.gd each time a paramterized test is encountered
|
||||
# for the first time.
|
||||
# FOR INTERNAL USE ONLY
|
||||
var parameter_handler = _parameter_handler :
|
||||
get: return _parameter_handler
|
||||
set(val):
|
||||
_parameter_handler = val
|
||||
_parameter_handler.set_logger(_lgr)
|
||||
|
||||
var _lgr = GutUtils.get_logger()
|
||||
# Local reference for the common logger.
|
||||
var logger = _lgr :
|
||||
get: return _lgr
|
||||
set(val):
|
||||
_lgr = val
|
||||
_lgr.set_gut(self)
|
||||
|
||||
var error_tracker = GutUtils.get_error_tracker()
|
||||
|
||||
var _add_children_to = self
|
||||
# Sets the object that GUT will add test objects to as it creates them. The
|
||||
# default is self, but can be set to other objects so that GUT is not obscured
|
||||
# by the objects added during tests.
|
||||
var add_children_to = self :
|
||||
get: return _add_children_to
|
||||
set(val): _add_children_to = val
|
||||
|
||||
|
||||
# ------------
|
||||
# Read only
|
||||
# ------------
|
||||
var _test_collector = GutUtils.TestCollector.new()
|
||||
func get_test_collector():
|
||||
return _test_collector
|
||||
|
||||
# var version = null :
|
||||
func get_version():
|
||||
return GutUtils.version_numbers.gut_version
|
||||
|
||||
var _orphan_counter = GutUtils.OrphanCounter.new()
|
||||
func get_orphan_counter():
|
||||
return _orphan_counter
|
||||
|
||||
# var _autofree = GutUtils.AutoFree.new()
|
||||
func get_autofree():
|
||||
return _orphan_counter.autofree
|
||||
|
||||
var _stubber = GutUtils.Stubber.new()
|
||||
func get_stubber():
|
||||
return _stubber
|
||||
|
||||
var _doubler = GutUtils.Doubler.new()
|
||||
func get_doubler():
|
||||
return _doubler
|
||||
|
||||
var _spy = GutUtils.Spy.new()
|
||||
func get_spy():
|
||||
return _spy
|
||||
|
||||
var _is_running = false
|
||||
func is_running():
|
||||
return _is_running
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# Private
|
||||
# ---------------------------
|
||||
var _should_print_versions = true # used to cut down on output in tests.
|
||||
var _should_print_summary = true
|
||||
|
||||
var _file_prefix = 'test_'
|
||||
var _inner_class_prefix = 'Test'
|
||||
|
||||
var _select_script = ''
|
||||
var _last_paint_time = 0.0
|
||||
var _strutils = GutUtils.Strutils.new()
|
||||
|
||||
# The instance that is created from _pre_run_script. Accessible from
|
||||
# get_pre_run_script_instance. These are created at the start of the run
|
||||
# and then referenced at the appropriate time. This allows us to validate the
|
||||
# scripts prior to running.
|
||||
var _pre_run_script_instance = null
|
||||
var _post_run_script_instance = null
|
||||
|
||||
var _script_name = null
|
||||
|
||||
# The instanced scripts. This is populated as the scripts are run.
|
||||
var _test_script_objects = []
|
||||
|
||||
var _waiting = false
|
||||
|
||||
# msecs ticks when run was started
|
||||
var _start_time = 0.0
|
||||
|
||||
# Collected Test instance for the current test being run.
|
||||
var _current_test = null
|
||||
var _pause_before_teardown = false
|
||||
|
||||
|
||||
# Used to cancel importing scripts if an error has occurred in the setup. This
|
||||
# prevents tests from being run if they were exported and ensures that the
|
||||
# error displayed is seen since importing generates a lot of text.
|
||||
#
|
||||
# TODO this appears to only be checked and never set anywhere. Verify that this
|
||||
# was not broken somewhere and remove if no longer used.
|
||||
var _cancel_import = false
|
||||
|
||||
# this is how long Gut will wait when there are items that must be queued free
|
||||
# when a test completes (due to calls to add_child_autoqfree)
|
||||
var _auto_queue_free_delay = .1
|
||||
|
||||
var _time_to_wait_for_final_queue_free = .5
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _init(override_logger=null):
|
||||
if(override_logger != null):
|
||||
logger = override_logger
|
||||
else:
|
||||
logger = logger # force setter logic
|
||||
|
||||
_doubler.set_stubber(_stubber)
|
||||
_doubler.set_spy(_spy)
|
||||
_doubler.set_gut(self)
|
||||
|
||||
update_loggers()
|
||||
|
||||
# Public for tests that set the logger. This makes it much easier to propigate
|
||||
# test loggers.
|
||||
func update_loggers():
|
||||
_doubler.set_logger(_lgr)
|
||||
_spy.set_logger(_lgr)
|
||||
_stubber.set_logger(_lgr)
|
||||
_test_collector.set_logger(_lgr)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Initialize controls
|
||||
# ------------------------------------------------------------------------------
|
||||
func _ready():
|
||||
if(_should_print_versions):
|
||||
_lgr.log('--- GUT ---')
|
||||
_lgr.info(str('using [', OS.get_user_data_dir(), '] for temporary output.'))
|
||||
|
||||
if(_select_script != null):
|
||||
select_script(_select_script)
|
||||
|
||||
_print_versions()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Runs right before free is called. Can't override `free`.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _notification(what):
|
||||
if(what == NOTIFICATION_PREDELETE):
|
||||
for ts in _test_script_objects:
|
||||
if(is_instance_valid(ts)):
|
||||
ts.free()
|
||||
|
||||
_test_script_objects = []
|
||||
|
||||
|
||||
func _print_versions(send_all = true):
|
||||
if(!_should_print_versions):
|
||||
return
|
||||
|
||||
var info = GutUtils.version_numbers.get_version_text()
|
||||
|
||||
if(send_all):
|
||||
p(info)
|
||||
else:
|
||||
_lgr.get_printer('gui').send(info + "\n")
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# Accessor code
|
||||
#
|
||||
# ---------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Set the log level. Use one of the various LOG_LEVEL_* constants.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _set_log_level(level):
|
||||
_log_level = max(level, 0)
|
||||
|
||||
# Level 0 settings
|
||||
_lgr.set_less_test_names(level == 0)
|
||||
# Explicitly always enabled
|
||||
_lgr.set_type_enabled(_lgr.types.normal, true)
|
||||
_lgr.set_type_enabled(_lgr.types.error, true)
|
||||
_lgr.set_type_enabled(_lgr.types.pending, true)
|
||||
|
||||
# Level 1 types
|
||||
_lgr.set_type_enabled(_lgr.types.warn, level > 0)
|
||||
_lgr.set_type_enabled(_lgr.types.deprecated, level > 0)
|
||||
|
||||
# Level 2 types
|
||||
_lgr.set_type_enabled(_lgr.types.passed, level > 1)
|
||||
_lgr.set_type_enabled(_lgr.types.info, level > 1)
|
||||
_lgr.set_type_enabled(_lgr.types.debug, level > 1)
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# Events
|
||||
#
|
||||
# ---------------------------
|
||||
func end_teardown_pause():
|
||||
_pause_before_teardown = false
|
||||
_waiting = false
|
||||
end_pause_before_teardown.emit()
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# Private
|
||||
#
|
||||
# ---------------------------
|
||||
func _log_test_children_warning(test_script):
|
||||
if(!_lgr.is_type_enabled(_lgr.types.orphan)):
|
||||
return
|
||||
|
||||
var kids = test_script.get_children()
|
||||
if(kids.size() > 1):
|
||||
var msg = ''
|
||||
if(_log_level == 2):
|
||||
msg = "Test script still has children when all tests finisehd.\n"
|
||||
for i in range(kids.size()):
|
||||
msg += str(" ", _strutils.type2str(kids[i]), "\n")
|
||||
msg += "You can use autofree, autoqfree, add_child_autofree, or add_child_autoqfree to automatically free objects."
|
||||
else:
|
||||
msg = str("Test script has ", kids.size(), " unfreed children. Increase log level for more details.")
|
||||
|
||||
_lgr.warn(msg)
|
||||
|
||||
|
||||
func _log_end_run():
|
||||
var summary = GutUtils.Summary.new(self)
|
||||
if(_should_print_summary):
|
||||
_orphan_counter.record_orphans("end_run")
|
||||
if(_lgr.is_type_enabled("orphan") and _orphan_counter.get_count() > 0):
|
||||
_lgr.log("\n\n\n")
|
||||
_lgr.orphan("==============================================")
|
||||
_lgr.orphan(str('= ', _orphan_counter.get_count(), ' Orphans'))
|
||||
_lgr.orphan("==============================================")
|
||||
_orphan_counter.log_all()
|
||||
_lgr.log("\n")
|
||||
else:
|
||||
_lgr.log("\n\n\n")
|
||||
|
||||
summary.log_end_run()
|
||||
|
||||
|
||||
func _validate_hook_script(path):
|
||||
var result = {
|
||||
valid = true,
|
||||
instance = null
|
||||
}
|
||||
|
||||
# empty path is valid but will have a null instance
|
||||
if(path == ''):
|
||||
return result
|
||||
|
||||
if(FileAccess.file_exists(path)):
|
||||
var inst = load(path).new()
|
||||
if(inst and inst is GutHookScript):
|
||||
result.instance = inst
|
||||
result.valid = true
|
||||
else:
|
||||
result.valid = false
|
||||
_lgr.error('The hook script [' + path + '] does not extend GutHookScript')
|
||||
else:
|
||||
result.valid = false
|
||||
_lgr.error('The hook script [' + path + '] does not exist.')
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Runs a hook script. Script must exist, and must extend
|
||||
# GutHookScript or addons/gut/hook_script.gd
|
||||
# ------------------------------------------------------------------------------
|
||||
func _run_hook_script(inst):
|
||||
if(inst != null):
|
||||
inst.gut = self
|
||||
await inst.run()
|
||||
return inst
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Initialize variables for each run of a single test script.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _init_run():
|
||||
var valid = true
|
||||
_test_collector.set_test_class_prefix(_inner_class_prefix)
|
||||
_test_script_objects = []
|
||||
_current_test = null
|
||||
_is_running = true
|
||||
|
||||
var pre_hook_result = _validate_hook_script(_pre_run_script)
|
||||
_pre_run_script_instance = pre_hook_result.instance
|
||||
var post_hook_result = _validate_hook_script(_post_run_script)
|
||||
_post_run_script_instance = post_hook_result.instance
|
||||
|
||||
valid = pre_hook_result.valid and post_hook_result.valid
|
||||
|
||||
return valid
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Print out run information and close out the run.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _end_run():
|
||||
await _run_hook_script(get_post_run_script_instance())
|
||||
|
||||
_orphan_counter.record_orphans("end_run")
|
||||
_orphan_counter.orphanage.clean()
|
||||
_log_end_run()
|
||||
_is_running = false
|
||||
|
||||
_export_results()
|
||||
end_run.emit()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Add additional export types here.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _export_results():
|
||||
if(_junit_xml_file != ''):
|
||||
_export_junit_xml()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _export_junit_xml():
|
||||
var exporter = GutUtils.JunitXmlExport.new()
|
||||
var output_file = _junit_xml_file
|
||||
|
||||
if(_junit_xml_timestamp):
|
||||
var ext = "." + output_file.get_extension()
|
||||
output_file = output_file.replace(ext, str("_", Time.get_unix_time_from_system(), ext))
|
||||
|
||||
var f_result = exporter.write_file(self, output_file)
|
||||
if(f_result == OK):
|
||||
p(str("Results saved to ", output_file))
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Print out the heading for a new script
|
||||
# ------------------------------------------------------------------------------
|
||||
func _print_script_heading(coll_script):
|
||||
if(_does_class_name_match(_inner_class_name, coll_script.inner_class_name)):
|
||||
_lgr.log(str("\n\n", coll_script.get_full_name()), _lgr.fmts.underline)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Yes if the class name is null or the script's class name includes class_name
|
||||
# ------------------------------------------------------------------------------
|
||||
func _does_class_name_match(the_class_name, script_class_name):
|
||||
return (the_class_name == null or the_class_name == '') or \
|
||||
(script_class_name != null and str(script_class_name).findn(the_class_name) != -1)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _create_script_instance(collected_script):
|
||||
var test_script = collected_script.get_new()
|
||||
|
||||
test_script.gut = self
|
||||
test_script.set_logger(_lgr)
|
||||
_add_children_to.add_child(test_script)
|
||||
_test_script_objects.append(test_script)
|
||||
test_script.wait_log_delay = wait_log_delay
|
||||
|
||||
if(!test_script._was_ready_called):
|
||||
test_script._do_ready_stuff()
|
||||
_lgr.warn(str("!!! YOU HAVE UPSET YOUR GUT !!!\n",
|
||||
"You have overridden _ready in [", collected_script.get_filename_and_inner(), "] ",
|
||||
"but it does not call super._ready(). New additions (or maybe old ",
|
||||
"by the time you see this) require that super._ready() is called.",
|
||||
"\n\n",
|
||||
"GUT is working around this infraction, but may not be able to in ",
|
||||
"the future. GUT also reserves the right to decide it does not want ",
|
||||
"to work around it in the future. ",
|
||||
"You should probably use before_all instead of _ready. I can think ",
|
||||
"of a few reasons why you would want to use _ready but I won't list ",
|
||||
"them here because I think they are bad ideas. I know they are bad ",
|
||||
"ideas because I did them. Hence the warning. This message is ",
|
||||
"intentially long so that it bothers you and you change your ways.\n\n",
|
||||
"Thank you for using GUT."))
|
||||
return test_script
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# returns self so it can be integrated into the yield call.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _wait_for_continue_button():
|
||||
p(PAUSE_MESSAGE, 0)
|
||||
_waiting = true
|
||||
return self
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _get_indexes_matching_script_name(script_name):
|
||||
var indexes = [] # empty runs all
|
||||
for i in range(_test_collector.scripts.size()):
|
||||
if(_test_collector.scripts[i].get_filename().find(script_name) != -1):
|
||||
indexes.append(i)
|
||||
return indexes
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _get_indexes_matching_path(path):
|
||||
var indexes = []
|
||||
for i in range(_test_collector.scripts.size()):
|
||||
if(_test_collector.scripts[i].path == path):
|
||||
indexes.append(i)
|
||||
return indexes
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Execute all calls of a parameterized test.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _run_parameterized_test(test_script, test_name):
|
||||
await _run_test(test_script, test_name, 0)
|
||||
|
||||
if(_current_test.assert_count == 0 and !_current_test.pending):
|
||||
_lgr.risky('Test did not assert')
|
||||
|
||||
if(_parameter_handler == null):
|
||||
_lgr.error(str('Parameterized test ', _current_test.name, ' did not call use_parameters for the default value of the parameter.'))
|
||||
_fail(str('Parameterized test ', _current_test.name, ' did not call use_parameters for the default value of the parameter.'))
|
||||
else:
|
||||
var index = 1
|
||||
while(!_parameter_handler.is_done()):
|
||||
var cur_assert_count = _current_test.assert_count
|
||||
await _run_test(test_script, test_name, index)
|
||||
if(_current_test.assert_count == cur_assert_count and !_current_test.pending):
|
||||
_lgr.risky('Test did not assert')
|
||||
index += 1
|
||||
|
||||
_parameter_handler = null
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Runs a single test given a test.gd instance and the name of the test to run.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _run_test(script_inst, test_name, param_index = -1):
|
||||
_lgr.log_test_name()
|
||||
_lgr.set_indent_level(1)
|
||||
|
||||
await script_inst.before_each()
|
||||
|
||||
start_test.emit(test_name)
|
||||
var test_id = str(script_inst.collected_script.get_filename_and_inner(), ':', test_name)
|
||||
if(param_index != -1):
|
||||
test_id += str('[', param_index, ']')
|
||||
error_tracker.start_test(test_id)
|
||||
|
||||
# Reset the time and frame tracking stats of the test
|
||||
script_inst.reset_start_times()
|
||||
await script_inst.call(test_name)
|
||||
|
||||
if(error_tracker.should_test_fail_from_errors(test_id)):
|
||||
script_inst._fail(str("Unexpected Errors:\n", error_tracker.get_fail_text_for_errors(test_id)))
|
||||
|
||||
error_tracker.end_test()
|
||||
# if the test called pause_before_teardown then await until
|
||||
# the continue button is pressed.
|
||||
if(_pause_before_teardown and !_ignore_pause_before_teardown):
|
||||
start_pause_before_teardown.emit()
|
||||
await _wait_for_continue_button().end_pause_before_teardown
|
||||
|
||||
script_inst.clear_signal_watcher()
|
||||
|
||||
await script_inst.after_each()
|
||||
|
||||
# Free up everything in the _autofree. Yield for a bit if we
|
||||
# have anything with a queue_free so that they have time to
|
||||
# free and are not found by the orphan counter.
|
||||
var aqf_count = _orphan_counter.autofree.get_queue_free_count()
|
||||
_orphan_counter.autofree.free_all()
|
||||
if(aqf_count > 0):
|
||||
await get_tree().create_timer(_auto_queue_free_delay).timeout
|
||||
|
||||
_orphan_counter.end_test(
|
||||
script_inst.collected_script.get_filename_and_inner(), test_name,
|
||||
_log_level > 0)
|
||||
|
||||
_doubler.get_ignored_methods().clear()
|
||||
|
||||
|
||||
func get_current_test_orphans():
|
||||
var sname = get_current_test_object().collected_script.get_ref().get_filename_and_inner()
|
||||
var tname = get_current_test_object().name
|
||||
_orphan_counter.record_orphans(sname, tname)
|
||||
return _orphan_counter.get_orphan_ids(sname, tname)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Calls before_all on the passed in test script and takes care of settings so all
|
||||
# logger output appears indented and with a proper heading
|
||||
#
|
||||
# Calls both pre-all-tests methods until prerun_setup is removed
|
||||
# ------------------------------------------------------------------------------
|
||||
func _call_before_all(test_script, collected_script):
|
||||
var before_all_test_obj = GutUtils.CollectedTest.new()
|
||||
before_all_test_obj.has_printed_name = false
|
||||
before_all_test_obj.name = 'before_all'
|
||||
|
||||
collected_script.setup_teardown_tests.append(before_all_test_obj)
|
||||
_current_test = before_all_test_obj
|
||||
|
||||
_lgr.inc_indent()
|
||||
await test_script.before_all()
|
||||
# before all does not need to assert anything so only mark it as run if
|
||||
# some assert was done.
|
||||
before_all_test_obj.was_run = before_all_test_obj.did_something()
|
||||
|
||||
_lgr.dec_indent()
|
||||
|
||||
_current_test = null
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Calls after_all on the passed in test script and takes care of settings so all
|
||||
# logger output appears indented and with a proper heading
|
||||
#
|
||||
# Calls both post-all-tests methods until postrun_teardown is removed.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _call_after_all(test_script, collected_script):
|
||||
var after_all_test_obj = GutUtils.CollectedTest.new()
|
||||
after_all_test_obj.has_printed_name = false
|
||||
after_all_test_obj.name = 'after_all'
|
||||
|
||||
collected_script.setup_teardown_tests.append(after_all_test_obj)
|
||||
_current_test = after_all_test_obj
|
||||
|
||||
_lgr.inc_indent()
|
||||
await test_script.after_all()
|
||||
# after all does not need to assert anything so only mark it as run if
|
||||
# some assert was done.
|
||||
after_all_test_obj.was_run = after_all_test_obj.did_something()
|
||||
_lgr.dec_indent()
|
||||
|
||||
_current_test = null
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _should_skip_script(test_script, collected_script):
|
||||
var skip_message = 'not skipped'
|
||||
var skip_value = test_script.get('skip_script')
|
||||
var should_skip = false
|
||||
|
||||
if(skip_value == null):
|
||||
skip_value = await test_script.should_skip_script()
|
||||
else:
|
||||
_lgr.deprecated('Using the skip_script var has been deprecated. Implement the new should_skip_script() method in your test instead.')
|
||||
|
||||
if(skip_value != null):
|
||||
if(typeof(skip_value) == TYPE_BOOL):
|
||||
should_skip = skip_value
|
||||
if(skip_value):
|
||||
skip_message = 'script marked to skip'
|
||||
elif(typeof(skip_value) == TYPE_STRING):
|
||||
should_skip = true
|
||||
skip_message = skip_value
|
||||
|
||||
if(should_skip):
|
||||
var msg = str('- [Script skipped]: ', skip_message)
|
||||
_lgr.inc_indent()
|
||||
_lgr.log(msg, _lgr.fmts.yellow)
|
||||
_lgr.dec_indent()
|
||||
collected_script.skip_reason = skip_message
|
||||
collected_script.was_skipped = true
|
||||
|
||||
return should_skip
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Run all tests in a script. This is the core logic for running tests.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _test_the_scripts(indexes=[]):
|
||||
|
||||
_print_versions(false)
|
||||
var is_valid = _init_run()
|
||||
if(!is_valid):
|
||||
_lgr.error('Something went wrong and the run was aborted.')
|
||||
return
|
||||
|
||||
await _run_hook_script(get_pre_run_script_instance())
|
||||
if(_pre_run_script_instance!= null and _pre_run_script_instance.should_abort()):
|
||||
_lgr.error('pre-run abort')
|
||||
end_run.emit()
|
||||
return
|
||||
|
||||
start_run.emit()
|
||||
_start_time = Time.get_ticks_msec()
|
||||
_last_paint_time = _start_time
|
||||
|
||||
var indexes_to_run = []
|
||||
if(indexes.size()==0):
|
||||
for i in range(_test_collector.scripts.size()):
|
||||
indexes_to_run.append(i)
|
||||
else:
|
||||
indexes_to_run = indexes
|
||||
|
||||
|
||||
# loop through scripts
|
||||
for test_indexes in range(indexes_to_run.size()):
|
||||
var coll_script = _test_collector.scripts[indexes_to_run[test_indexes]]
|
||||
|
||||
if(coll_script.tests.size() > 0):
|
||||
_lgr.set_indent_level(0)
|
||||
_print_script_heading(coll_script)
|
||||
|
||||
if(!coll_script.is_loaded):
|
||||
break
|
||||
|
||||
start_script.emit(coll_script)
|
||||
|
||||
var test_script = _create_script_instance(coll_script)
|
||||
_doubler.set_strategy(_double_strategy)
|
||||
|
||||
# ----
|
||||
# SHORTCIRCUIT
|
||||
# skip_script logic
|
||||
if(await _should_skip_script(test_script, coll_script)):
|
||||
_orphan_counter.record_orphans(coll_script.get_full_name())
|
||||
continue
|
||||
# ----
|
||||
|
||||
# !!!
|
||||
# Hack so there isn't another indent to this monster of a method. if
|
||||
# inner class is set and we do not have a match then empty the tests
|
||||
# for the current test.
|
||||
# !!!
|
||||
if(!_does_class_name_match(_inner_class_name, coll_script.inner_class_name)):
|
||||
coll_script.tests = []
|
||||
else:
|
||||
coll_script.was_run = true
|
||||
await _call_before_all(test_script, coll_script)
|
||||
|
||||
_orphan_counter.record_orphans(coll_script.get_full_name())
|
||||
# Each test in the script
|
||||
for i in range(coll_script.tests.size()):
|
||||
_stubber.clear()
|
||||
_spy.clear()
|
||||
_current_test = coll_script.tests[i]
|
||||
|
||||
if((_unit_test_name != '' and _current_test.name.find(_unit_test_name) > -1) or
|
||||
(_unit_test_name == '')):
|
||||
|
||||
var ticks_before := Time.get_ticks_usec()
|
||||
|
||||
if(_current_test.arg_count > 1):
|
||||
_lgr.error(str('Parameterized test ', _current_test.name,
|
||||
' has too many parameters: ', _current_test.arg_count, '.'))
|
||||
elif(_current_test.arg_count == 1):
|
||||
_current_test.was_run = true
|
||||
await _run_parameterized_test(test_script, _current_test.name)
|
||||
else:
|
||||
_current_test.was_run = true
|
||||
await _run_test(test_script, _current_test.name)
|
||||
|
||||
if(!_current_test.did_something()):
|
||||
_lgr.risky(str(_current_test.name, ' did not assert'))
|
||||
|
||||
_current_test.has_printed_name = false
|
||||
|
||||
_current_test.time_taken = (Time.get_ticks_usec() - ticks_before) / 1000000.0
|
||||
|
||||
end_test.emit()
|
||||
|
||||
# After each test, check to see if we shoudl wait a frame to
|
||||
# paint based on how much time has elapsed since we last 'painted'
|
||||
if(paint_after > 0.0):
|
||||
var now = Time.get_ticks_msec()
|
||||
var time_since = (now - _last_paint_time) / 1000.0
|
||||
if(time_since > paint_after):
|
||||
_last_paint_time = now
|
||||
await get_tree().process_frame
|
||||
|
||||
_current_test = null
|
||||
_lgr.dec_indent()
|
||||
|
||||
if(_does_class_name_match(_inner_class_name, coll_script.inner_class_name)):
|
||||
await _call_after_all(test_script, coll_script)
|
||||
|
||||
_orphan_counter.end_script(
|
||||
coll_script.get_filename_and_inner(),
|
||||
_log_level > 0)
|
||||
|
||||
_log_test_children_warning(test_script)
|
||||
# This might end up being very resource intensive if the scripts
|
||||
# don't clean up after themselves. Might have to consolidate output
|
||||
# into some other structure and kill the script objects with
|
||||
# test_script.free() instead of remove_at child.
|
||||
_add_children_to.remove_child(test_script)
|
||||
|
||||
_lgr.set_indent_level(0)
|
||||
if(test_script.get_assert_count() > 0):
|
||||
var script_sum = str(coll_script.get_passing_test_count(), '/', coll_script.get_ran_test_count(), ' passed.')
|
||||
_lgr.log(script_sum, _lgr.fmts.bold)
|
||||
|
||||
test_script.queue_free()
|
||||
end_script.emit()
|
||||
# END TEST SCRIPT LOOP
|
||||
|
||||
_lgr.set_indent_level(0)
|
||||
# Give anything that is queued to be freed time to be freed before we count
|
||||
# the orphans. Without this, the last test's awaiter won't be freed
|
||||
# yet, which messes with the orphans total. There could also be objects
|
||||
# the user has queued to be freed as well.
|
||||
# Bump number from .1 to .5 when inner classes that were not run were still
|
||||
# appearing as orphans. Maybe this could loop through the orpahns looking
|
||||
# for entries that were not freed but are queued to be freed and wait unitl
|
||||
# they are all gone. ".5" is a lot easier.
|
||||
await get_tree().create_timer(_time_to_wait_for_final_queue_free).timeout
|
||||
_end_run()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _pass(text=''):
|
||||
if(_current_test):
|
||||
_current_test.add_pass(text)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Returns an empty string or "(call #x) " if the current test being run has
|
||||
# parameters. The
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_call_count_text():
|
||||
var to_return = ''
|
||||
if(_parameter_handler != null):
|
||||
# This uses get_call_count -1 because test.gd's use_parameters method
|
||||
# should have been called before we get to any calls for this method
|
||||
# just due to how use_parameters works. There isn't a way to know
|
||||
# whether we are before or after that call.
|
||||
to_return = str('params[', _parameter_handler.get_call_count() -1, '] ')
|
||||
return to_return
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _fail(text=''):
|
||||
if(_current_test != null):
|
||||
var line_number = _extract_line_number(_current_test)
|
||||
var line_text = ' at line ' + str(line_number)
|
||||
p(line_text, LOG_LEVEL_FAIL_ONLY)
|
||||
# format for summary
|
||||
line_text = "\n " + line_text
|
||||
var call_count_text = get_call_count_text()
|
||||
_current_test.line_number = line_number
|
||||
_current_test.add_fail(call_count_text + text + line_text)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func _pending(text=''):
|
||||
if(_current_test):
|
||||
_current_test.add_pending(text)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Extracts the line number from curren stacktrace by matching the test case name
|
||||
# ------------------------------------------------------------------------------
|
||||
func _extract_line_number(current_test):
|
||||
var line_number = -1
|
||||
# if stack trace available than extraxt the test case line number
|
||||
var stackTrace = get_stack()
|
||||
if(stackTrace!=null):
|
||||
for index in stackTrace.size():
|
||||
var line = stackTrace[index]
|
||||
var function = line.get("function")
|
||||
if function == current_test.name:
|
||||
line_number = line.get("line")
|
||||
return line_number
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Gets all the files in a directory and all subdirectories if include_subdirectories
|
||||
# is true. The files returned are all sorted by name.
|
||||
# ------------------------------------------------------------------------------
|
||||
func _get_files(path, prefix, suffix):
|
||||
var files = []
|
||||
var directories = []
|
||||
# ignore addons/gut per issue 294
|
||||
if(path == 'res://addons/gut'):
|
||||
return [];
|
||||
|
||||
var d = DirAccess.open(path)
|
||||
d.include_hidden = false
|
||||
d.include_navigational = false
|
||||
|
||||
# Traversing a directory is kinda odd. You have to start the process of
|
||||
# listing the contents of a directory with list_dir_begin then use get_next
|
||||
# until it returns an empty string. Then I guess you should end it.
|
||||
d.list_dir_begin()
|
||||
var fs_item = d.get_next()
|
||||
var full_path = ''
|
||||
while(fs_item != ''):
|
||||
full_path = path.path_join(fs_item)
|
||||
|
||||
# MUST use FileAccess since d.file_exists returns false for exported
|
||||
# projects
|
||||
if(FileAccess.file_exists(full_path)):
|
||||
if(fs_item.begins_with(prefix) and fs_item.ends_with(suffix)):
|
||||
files.append(full_path)
|
||||
# MUST use DirAccess, d.dir_exists is false for exported projects.
|
||||
elif(include_subdirectories and DirAccess.dir_exists_absolute(full_path)):
|
||||
directories.append(full_path)
|
||||
|
||||
fs_item = d.get_next()
|
||||
d.list_dir_end()
|
||||
|
||||
for dir in range(directories.size()):
|
||||
var dir_files = _get_files(directories[dir], prefix, suffix)
|
||||
for i in range(dir_files.size()):
|
||||
files.append(dir_files[i])
|
||||
|
||||
files.sort()
|
||||
return files
|
||||
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# public
|
||||
#
|
||||
# ---------------------------
|
||||
|
||||
func get_elapsed_time() -> float:
|
||||
var to_return = 0.0
|
||||
if(_start_time != 0.0):
|
||||
to_return = Time.get_ticks_msec() - _start_time
|
||||
to_return = to_return / 1000.0
|
||||
|
||||
return to_return
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Conditionally prints the text to the console/results variable based on the
|
||||
# current log level and what level is passed in. Whenever currently in a test,
|
||||
# the text will be indented under the test. It can be further indented if
|
||||
# desired.
|
||||
#
|
||||
# The first time output is generated when in a test, the test name will be
|
||||
# printed.
|
||||
# ------------------------------------------------------------------------------
|
||||
func p(text, level=0):
|
||||
var str_text = str(text)
|
||||
|
||||
if(level <= GutUtils.nvl(_log_level, 0)):
|
||||
_lgr.log(str_text)
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# RUN TESTS/ADD SCRIPTS
|
||||
#
|
||||
# ---------------------------
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Runs all the scripts that were added using add_script
|
||||
# ------------------------------------------------------------------------------
|
||||
func test_scripts(_run_rest=false):
|
||||
if(_script_name != null and _script_name != ''):
|
||||
var indexes = _get_indexes_matching_script_name(_script_name)
|
||||
if(indexes == []):
|
||||
_lgr.error(str(
|
||||
"Could not find script matching '", _script_name, "'.\n",
|
||||
"Check your directory settings and Script Prefix/Suffix settings."))
|
||||
end_run.emit()
|
||||
else:
|
||||
_test_the_scripts(indexes)
|
||||
else:
|
||||
_test_the_scripts([])
|
||||
|
||||
# alias
|
||||
func run_tests(run_rest=false):
|
||||
test_scripts(run_rest)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Runs a single script passed in.
|
||||
# ------------------------------------------------------------------------------
|
||||
# func run_test_script(script):
|
||||
# _test_collector.set_test_class_prefix(_inner_class_prefix)
|
||||
# _test_collector.clear()
|
||||
# _test_collector.add_script(script)
|
||||
# _test_the_scripts()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Adds a script to be run when test_scripts called.
|
||||
# ------------------------------------------------------------------------------
|
||||
func add_script(script):
|
||||
# if(!Engine.is_editor_hint()):
|
||||
_test_collector.set_test_class_prefix(_inner_class_prefix)
|
||||
_test_collector.add_script(script)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Add all scripts in the specified directory that start with the prefix and end
|
||||
# with the suffix. Does not look in sub directories. Can be called multiple
|
||||
# times.
|
||||
# ------------------------------------------------------------------------------
|
||||
func add_directory(path, prefix=_file_prefix, suffix=".gd"):
|
||||
# check for '' b/c the calls to addin the exported directories 1-6 will pass
|
||||
# '' if the field has not been populated. This will cause res:// to be
|
||||
# processed which will include all files if include_subdirectories is true.
|
||||
if(path == '' or path == null):
|
||||
return
|
||||
|
||||
var dir = DirAccess.open(path)
|
||||
if(dir == null):
|
||||
_lgr.error(str('The path [', path, '] does not exist.'))
|
||||
else:
|
||||
var files = _get_files(path, prefix, suffix)
|
||||
for i in range(files.size()):
|
||||
if(_script_name == null or _script_name == '' or \
|
||||
(_script_name != null and files[i].findn(_script_name) != -1)):
|
||||
add_script(files[i])
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# This will try to find a script in the list of scripts to test that contains
|
||||
# the specified script name. It does not have to be a full match. It will
|
||||
# select the first matching occurrence so that this script will run when run_tests
|
||||
# is called. Works the same as the select_this_one option of add_script.
|
||||
#
|
||||
# returns whether it found a match or not
|
||||
# ------------------------------------------------------------------------------
|
||||
func select_script(script_name):
|
||||
_script_name = script_name
|
||||
_select_script = script_name
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func export_tests(path=_export_path):
|
||||
if(path == null):
|
||||
_lgr.error('You must pass a path or set the export_path before calling export_tests')
|
||||
else:
|
||||
var result = _test_collector.export_tests(path)
|
||||
if(result):
|
||||
_lgr.info(_test_collector.to_s())
|
||||
_lgr.info("Exported to " + path)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func import_tests(path=_export_path):
|
||||
if(!FileAccess.file_exists(path)):
|
||||
_lgr.error(str('Cannot import tests: the path [', path, '] does not exist.'))
|
||||
else:
|
||||
_test_collector.clear()
|
||||
var result = _test_collector.import_tests(path)
|
||||
if(result):
|
||||
_lgr.info("\n" + _test_collector.to_s())
|
||||
_lgr.info("Imported from " + path)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func import_tests_if_none_found():
|
||||
if(!_cancel_import and _test_collector.scripts.size() == 0):
|
||||
import_tests()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func export_if_tests_found():
|
||||
if(_test_collector.scripts.size() > 0):
|
||||
export_tests()
|
||||
|
||||
# ---------------------------
|
||||
#
|
||||
# MISC
|
||||
#
|
||||
# ---------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func maximize():
|
||||
_lgr.deprecated('gut.maximize')
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Clears the text of the text box. This resets all counters.
|
||||
# ------------------------------------------------------------------------------
|
||||
func clear_text():
|
||||
_lgr.deprecated('gut.clear_text')
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get the number of tests that were ran
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_test_count():
|
||||
return _test_collector.get_ran_test_count()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
## Get the number of assertions that were made
|
||||
func get_assert_count():
|
||||
return _test_collector.get_assert_count()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
## Get the number of assertions that passed
|
||||
func get_pass_count():
|
||||
return _test_collector.get_pass_count()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
## Get the number of assertions that failed
|
||||
func get_fail_count():
|
||||
return _test_collector.get_fail_count()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
## Get the number of tests flagged as pending
|
||||
func get_pending_count():
|
||||
return _test_collector.get_pending_count()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Call this method to make the test pause before teardown so that you can inspect
|
||||
# anything that you have rendered to the screen.
|
||||
# ------------------------------------------------------------------------------
|
||||
func pause_before_teardown():
|
||||
_pause_before_teardown = true;
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Returns the script object instance that is currently being run.
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_current_script_object():
|
||||
var to_return = null
|
||||
if(_test_script_objects.size() > 0):
|
||||
to_return = _test_script_objects[-1]
|
||||
return to_return
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_current_test_object():
|
||||
return _current_test
|
||||
|
||||
|
||||
## Returns a summary.gd object that contains all the information about
|
||||
## the run results.
|
||||
func get_summary():
|
||||
return GutUtils.Summary.new(self)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_pre_run_script_instance():
|
||||
return _pre_run_script_instance
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_post_run_script_instance():
|
||||
return _post_run_script_instance
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func show_orphans(should):
|
||||
_lgr.set_type_enabled(_lgr.types.orphan, should)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
func get_logger():
|
||||
return _lgr
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
## Returns the number of test scripts. Inner Test classes each count as a
|
||||
## script.
|
||||
func get_test_script_count():
|
||||
return _test_script_objects.size()
|
||||
|
||||
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# The MIT License (MIT)
|
||||
# =====================
|
||||
#
|
||||
# Copyright (c) 2025 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.
|
||||
#
|
||||
# ##############################################################################
|
||||
Reference in New Issue
Block a user