diff --git a/CHANGES.md b/CHANGES.md index 20d3f705..b7756a25 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,13 @@ # Release notes All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + + +# 6.6.1 +* __Issue 60__: Improved signal assert failure messages in some cases by having them include a list of signals that were emitted for the object. +* __Issue 88__: Fixed issue where you couldn't specify the config_file from the command line. +* __Issue 95__: Fixed issue where sometimes Gut can end up clearing files from `res:\\` when using doubling. + # 6.6.0 ## Fixes diff --git a/README.md b/README.md index 0b130455..f8ef1417 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ### Godot 3.1 I've started a [3.1 branch](https://github.com/bitwes/Gut/tree/godot_3_1) that I will be keeping inline with master. I've gotten it to run but there are issues. Check open issues and the [3.1 wiki page](https://github.com/bitwes/Gut/wiki/Godot-3.1-Alpha). -# Gut 6.6.0 +# Gut 6.6.1 GUT (Godot Unit Test) is a utility for writing tests for your Godot Engine game. It allows you to write tests for your gdscript in gdscript. More info can be found in the [wiki](https://github.com/bitwes/Gut/wiki). diff --git a/addons/gut/doubler.gd b/addons/gut/doubler.gd index 28e95118..b40695d4 100644 --- a/addons/gut/doubler.gd +++ b/addons/gut/doubler.gd @@ -155,23 +155,33 @@ func double_scene(path): _double_scene_and_script(path, temp_path) return load(temp_path) -func double(obj): - return load(_double(obj)) +func double(path): + return load(_double(path)) func clear_output_directory(): - var d = Directory.new() - d.open(_output_dir) - d.list_dir_begin(true) - var files = [] - var f = d.get_next() - while(f != ''): - d.remove(f) - f = d.get_next() + var did = false + if(_output_dir.find('user://') == 0): + var d = Directory.new() + var result = d.open(_output_dir) + # BIG GOTCHA HERE. If it cannot open the dir w/ erro 31, then the + # directory becomes res:// and things go on normally and gut clears out + # out res:// which is SUPER BAD. + if(result == OK): + d.list_dir_begin(true) + var files = [] + var f = d.get_next() + while(f != ''): + print('deleting ', f) + d.remove(f) + f = d.get_next() + did = true + return did func delete_output_directory(): - clear_output_directory() - var d = Directory.new() - d.remove(_output_dir) + var did = clear_output_directory() + if(did): + var d = Directory.new() + d.remove(_output_dir) func set_use_unique_names(should): _use_unique_names = should diff --git a/addons/gut/gut.gd b/addons/gut/gut.gd index 0a03b46b..bb76b049 100644 --- a/addons/gut/gut.gd +++ b/addons/gut/gut.gd @@ -28,7 +28,7 @@ ################################################################################ # View readme for usage details. # -# Version 6.6.0 +# Version 6.6.1 ################################################################################ extends "res://addons/gut/gut_gui.gd" diff --git a/addons/gut/gut_cmdln.gd b/addons/gut/gut_cmdln.gd index 8aaf5067..58d57939 100644 --- a/addons/gut/gut_cmdln.gd +++ b/addons/gut/gut_cmdln.gd @@ -37,7 +37,7 @@ # See the readme for a list of options and examples. You can also use the -gh # option to get more information about how to use the command line interface. # -# Version 6.6.0 +# Version 6.6.1 ################################################################################ extends SceneTree @@ -465,8 +465,7 @@ func _init(): o.parse() extract_command_line_options(o, opt_resolver.cmd_opts) var load_result = \ - load_options_from_config_file(options.config_file, opt_resolver.config_opts) - + load_options_from_config_file(opt_resolver.get_value('config_file'), opt_resolver.config_opts) if(load_result == -1): # -1 indicates json parse error quit() else: diff --git a/addons/gut/plugin.cfg b/addons/gut/plugin.cfg index 999c86ee..6602f19f 100644 --- a/addons/gut/plugin.cfg +++ b/addons/gut/plugin.cfg @@ -3,5 +3,5 @@ name="Gut" description="Unit Testing tool for Godot." author="Butch Wesley" -version="6.6.0" +version="6.6.1" script="gut_plugin.gd" diff --git a/addons/gut/signal_watcher.gd b/addons/gut/signal_watcher.gd index 93d3ea0e..d4e35fa9 100644 --- a/addons/gut/signal_watcher.gd +++ b/addons/gut/signal_watcher.gd @@ -153,3 +153,14 @@ func clear(): if(wr.get_ref()): obj.disconnect(signal_name, self, '_on_watched_signal') _watched_signals.clear() + +# Returns a list of all the signal names that were emitted by the object. +# If the object is not being watched then an empty list is returned. +func get_signals_emitted(obj): + var emitted = [] + if(is_watching_object(obj)): + for signal_name in _watched_signals[obj]: + if(_watched_signals[obj][signal_name].size() > 0): + emitted.append(signal_name) + + return emitted diff --git a/addons/gut/test.gd b/addons/gut/test.gd index 378718ac..a4a9787d 100644 --- a/addons/gut/test.gd +++ b/addons/gut/test.gd @@ -189,6 +189,13 @@ func _fail_if_not_watching(object): 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), ")") + # ####################### # Virtual Methods # ####################### @@ -487,7 +494,7 @@ func assert_signal_emitted(object, signal_name, text=""): if(_signal_watcher.did_emit(object, signal_name)): _pass(disp) else: - _fail(disp) + _fail(_get_fail_msg_including_emitted_signals(disp, object)) # ------------------------------------------------------------------------------ # Asserts that a signal has not been emitted. @@ -522,7 +529,8 @@ func assert_signal_emitted_with_parameters(object, signal_name, parameters, inde else: _fail(str(disp, parms_got)) else: - _fail(str('Object ', object, ' did not emit signal [', signal_name, ']')) + 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. @@ -538,7 +546,7 @@ func assert_signal_emit_count(object, signal_name, times, text=""): if(count== times): _pass(disp) else: - _fail(disp) + _fail(_get_fail_msg_including_emitted_signals(disp, object)) # ------------------------------------------------------------------------------ # Assert that the passed in object has the specfied signal diff --git a/test/unit/test_signal_watcher.gd b/test/unit/test_signal_watcher.gd index 316451b9..623d2292 100644 --- a/test/unit/test_signal_watcher.gd +++ b/test/unit/test_signal_watcher.gd @@ -246,4 +246,18 @@ func test_clearing_ignores_freed_objecdts(): yield(yield_for(0.5), YIELD) gr.sw.clear() end_test() - #assert_signal_emitted(gr.so, 'script_signal') + +# #################### +# Get signals emitted +# #################### +func test_when_signal_emitted_it_exists_in_list_of_signals_emitted(): + gr.sw.watch_signals(gr.so) + gr.so.emit_signal(SIGNALS.NO_PARAMETERS) + gr.so.emit_signal(SIGNALS.SOME_SIGNAL) + assert_has(gr.sw.get_signals_emitted(gr.so), SIGNALS.NO_PARAMETERS) + assert_has(gr.sw.get_signals_emitted(gr.so), SIGNALS.SOME_SIGNAL) + assert_eq(gr.sw.get_signals_emitted(gr.so).size(), 2) + +func test_when_passed_non_watched_obj_emitted_signals_is_empty(): + gr.so.emit_signal(SIGNALS.NO_PARAMETERS) + assert_eq(gr.sw.get_signals_emitted(gr.so).size(), 0) diff --git a/test/unit/test_test.gd b/test/unit/test_test.gd index 92f8d204..9c3daaf5 100644 --- a/test/unit/test_test.gd +++ b/test/unit/test_test.gd @@ -802,6 +802,35 @@ class TestSignalAsserts: gr.test.assert_has_signal(gr.signal_object, SIGNALS.SCRIPT_SIGNAL) assert_pass(gr.test) + func test_when_signal_emitted_fails_emitted_signals_are_listed(): + gr.test.watch_signals(gr.signal_object) + gr.signal_object.emit_signal(SIGNALS.NO_PARAMETERS) + gr.signal_object.emit_signal(SIGNALS.SOME_SIGNAL) + gr.test.assert_signal_emitted(gr.signal_object, SIGNALS.SCRIPT_SIGNAL) + var text = gr.test._fail_pass_text[0] + assert_string_contains(text, SIGNALS.NO_PARAMETERS) + assert_string_contains(text, SIGNALS.SOME_SIGNAL) + + func test_when_signal_count_fails_then_emitted_signals_are_listed(): + gr.test.watch_signals(gr.signal_object) + gr.signal_object.emit_signal(SIGNALS.NO_PARAMETERS) + gr.signal_object.emit_signal(SIGNALS.SCRIPT_SIGNAL) + gr.signal_object.emit_signal(SIGNALS.SOME_SIGNAL) + gr.test.assert_signal_emit_count(gr.signal_object, SIGNALS.SCRIPT_SIGNAL, 2) + var text = gr.test._fail_pass_text[0] + assert_string_contains(text, SIGNALS.NO_PARAMETERS) + assert_string_contains(text, SIGNALS.SOME_SIGNAL) + + func test_when_signal_emit_with_parameters_fails_because_signal_was_not_emitted_then_signals_are_listed(): + gr.test.watch_signals(gr.signal_object) + gr.signal_object.emit_signal(SIGNALS.NO_PARAMETERS) + gr.signal_object.emit_signal(SIGNALS.SOME_SIGNAL) + gr.test.assert_signal_emitted_with_parameters(gr.signal_object, SIGNALS.SCRIPT_SIGNAL, [0]) + var text = gr.test._fail_pass_text[0] + assert_string_contains(text, SIGNALS.NO_PARAMETERS) + assert_string_contains(text, SIGNALS.SOME_SIGNAL) + + # TODO rename tests since they are now in an inner class. See NOTE at top about naming. class TestExtendAsserts: extends BaseTestClass