diff options
Diffstat (limited to 'modules/gdscript/tests')
7 files changed, 83 insertions, 8 deletions
diff --git a/modules/gdscript/tests/README.md b/modules/gdscript/tests/README.md index 361d586d32..cea251bab5 100644 --- a/modules/gdscript/tests/README.md +++ b/modules/gdscript/tests/README.md @@ -6,3 +6,44 @@ and output files. See the [Integration tests for GDScript documentation](https://docs.godotengine.org/en/latest/contributing/development/core_and_modules/unit_testing.html#integration-tests-for-gdscript) for information about creating and running GDScript integration tests. + +# GDScript Autocompletion tests + +The `script/completion` folder contains test for the GDScript autocompletion. + +Each test case consists of at least one `.gd` file, which contains the code, and one `.cfg` file, which contains expected results and configuration. Inside of the GDScript file the character `➡` represents the cursor position, at which autocompletion is invoked. + +The config file contains two section: + +`[input]` contains keys that configure the test environment. The following keys are possible: + +- `cs: boolean = false`: If `true`, the test will be skipped when running a non C# build. +- `use_single_quotes: boolean = false`: Configures the corresponding editor setting for the test. +- `scene: String`: Allows to specify a scene which is opened while autocompletion is performed. If this is not set the test runner will search for a `.tscn` file with the same basename as the GDScript file. If that isn't found either, autocompletion will behave as if no scene was opened. + +`[output]` specifies the expected results for the test. The following key are supported: + +- `include: Array`: An unordered list of suggestions that should be in the result. Each entry is one dictionary with the following keys: `display`, `insert_text`, `kind`, `location`, which correspond to the suggestion struct which is used in the code. The runner only tests against specified keys, so in most cases `display` will suffice. +- `exclude: Array`: An array of suggestions which should not be in the result. The entries take the same form as for `include`. +- `call_hint: String`: The expected call hint returned by autocompletion. +- `forced: boolean`: Whether autocompletion is expected to force opening a completion window. + +Tests will only test against entries in `[output]` that were specified. + +## Writing autocompletion tests + +To avoid failing edge cases a certain behaviour needs to be tested multiple times. Some things that tests should account for: + +- All possible types: Test with all possible types that apply to the tested behaviour. (For the last points testing against `SCRIPT` and `CLASS` should suffice. `CLASS` can be obtained through C#, `SCRIPT` through GDScript. Relying on autoloads to be of type `SCRIPT` is not good, since this might change in the future.) + + - `BUILTIN` + - `NATIVE` + - GDScripts (with `class_name` as well as `preload`ed) + - C# (as standin for all other language bindings) (with `class_name` as well as `preload`ed) + - Autoloads + +- Possible contexts: the completion might be placed in different places of the program. e.g: + - initializers of class members + - directly inside a suite + - assignments inside a suite + - as parameter to a call diff --git a/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg index 4edee46039..27e695d245 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg @@ -1,4 +1,4 @@ [output] -expected=[ +include=[ {"display": "autoplay"}, ] diff --git a/modules/gdscript/tests/scripts/runtime/features/free_is_callable.gd b/modules/gdscript/tests/scripts/runtime/features/free_is_callable.gd new file mode 100644 index 0000000000..b9746a8207 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/free_is_callable.gd @@ -0,0 +1,10 @@ +func test(): + var node := Node.new() + var callable: Callable = node.free + callable.call() + print(node) + + node = Node.new() + callable = node["free"] + callable.call() + print(node) diff --git a/modules/gdscript/tests/scripts/runtime/features/free_is_callable.out b/modules/gdscript/tests/scripts/runtime/features/free_is_callable.out new file mode 100644 index 0000000000..97bfc46d96 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/free_is_callable.out @@ -0,0 +1,3 @@ +GDTEST_OK +<Freed Object> +<Freed Object> diff --git a/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.gd new file mode 100644 index 0000000000..11f064bb83 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.gd @@ -0,0 +1,10 @@ +func test(): + print(print) + print(len) + + prints.callv([1, 2, 3]) + print(mini.call(1, 2)) + print(len.bind("abc").call()) + + const ABSF = absf + print(ABSF.call(-1.2)) diff --git a/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.out new file mode 100644 index 0000000000..91549b9345 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/utility_func_as_callable.out @@ -0,0 +1,7 @@ +GDTEST_OK +@GlobalScope::print (Callable) +@GDScript::len (Callable) +1 2 3 +1 +3 +1.2 diff --git a/modules/gdscript/tests/test_completion.h b/modules/gdscript/tests/test_completion.h index abc34bd4bf..fd6b5321e6 100644 --- a/modules/gdscript/tests/test_completion.h +++ b/modules/gdscript/tests/test_completion.h @@ -128,19 +128,23 @@ static void test_directory(const String &p_dir) { EditorSettings::get_singleton()->set_setting("text_editor/completion/use_single_quotes", conf.get_value("input", "use_single_quotes", false)); List<Dictionary> include; - to_dict_list(conf.get_value("result", "include", Array()), include); + to_dict_list(conf.get_value("output", "include", Array()), include); List<Dictionary> exclude; - to_dict_list(conf.get_value("result", "exclude", Array()), exclude); + to_dict_list(conf.get_value("output", "exclude", Array()), exclude); List<ScriptLanguage::CodeCompletionOption> options; String call_hint; bool forced; Node *owner = nullptr; - if (dir->file_exists(next.get_basename() + ".tscn")) { - String project_path = "res://completion"; - Ref<PackedScene> scene = ResourceLoader::load(project_path.path_join(next.get_basename() + ".tscn"), "PackedScene"); + if (conf.has_section_key("input", "scene")) { + Ref<PackedScene> scene = ResourceLoader::load(conf.get_value("input", "scene"), "PackedScene"); + if (scene.is_valid()) { + owner = scene->instantiate(); + } + } else if (dir->file_exists(next.get_basename() + ".tscn")) { + Ref<PackedScene> scene = ResourceLoader::load(path.path_join(next.get_basename() + ".tscn"), "PackedScene"); if (scene.is_valid()) { owner = scene->instantiate(); } @@ -169,8 +173,8 @@ static void test_directory(const String &p_dir) { CHECK_MESSAGE(contains_excluded.is_empty(), "Autocompletion suggests illegal option '", contains_excluded, "' for '", path.path_join(next), "'."); CHECK(include.is_empty()); - String expected_call_hint = conf.get_value("result", "call_hint", call_hint); - bool expected_forced = conf.get_value("result", "forced", forced); + String expected_call_hint = conf.get_value("output", "call_hint", call_hint); + bool expected_forced = conf.get_value("output", "forced", forced); CHECK(expected_call_hint == call_hint); CHECK(expected_forced == forced); |