浏览代码

Allow specifying a scene in completion tests

HolonProduction 1 年之前
父节点
当前提交
92a7c26806

+ 41 - 0
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

+ 1 - 1
modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg

@@ -1,4 +1,4 @@
 [output]
-expected=[
+include=[
     {"display": "autoplay"},
 ]

+ 11 - 7
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);