From 1370f63325f7b2693271316ee6ad9a5c474d797f Mon Sep 17 00:00:00 2001 From: miguel Date: Tue, 26 Nov 2024 20:41:53 +0000 Subject: [PATCH] Use correct category for entity instances (#212) --- .github/workflows/pandora-ci.yml | 2 +- addons/gdUnit4/bin/GdUnitCmdTool.gd | 12 ++-- addons/gdUnit4/plugin.cfg | 2 +- .../gdUnit4/src/asserts/GdAssertMessages.gd | 4 +- .../src/asserts/GdUnitFuncAssertImpl.gd | 30 ++++++---- .../src/asserts/GdUnitSignalAssertImpl.gd | 8 +++ addons/gdUnit4/src/core/GdArrayTools.gd | 8 +++ addons/gdUnit4/src/core/GdUnitFileAccess.gd | 11 ++-- addons/gdUnit4/src/core/GdUnitSingleton.gd | 4 +- .../core/discovery/GdUnitTestDiscoverGuard.gd | 55 ++++++++++++++++++- .../core/execution/GdUnitExecutionContext.gd | 2 + .../stages/GdUnitTestCaseAfterStage.gd | 3 +- .../stages/GdUnitTestSuiteAfterStage.gd | 2 - .../stages/GdUnitTestSuiteExecutionStage.gd | 42 ++++++++++++++ .../gdUnit4/src/core/parse/GdScriptParser.gd | 6 +- .../src/core/thread/GdUnitThreadContext.gd | 13 +++-- .../gdUnit4/src/report/GdUnitHtmlPatterns.gd | 5 ++ .../gdUnit4/src/report/GdUnitReportSummary.gd | 8 ++- .../src/report/template/css/styles.css | 11 +++- .../src/report/template/folder_report.html | 3 + addons/gdUnit4/src/report/template/index.html | 3 + .../src/report/template/suite_report.html | 3 + addons/pandora/model/entity.gd | 13 ++++- pandora/categories.gd | 19 ++----- test/api_test.gd | 14 +++++ test/backend/entity_backend_test.gd | 1 - 26 files changed, 220 insertions(+), 64 deletions(-) diff --git a/.github/workflows/pandora-ci.yml b/.github/workflows/pandora-ci.yml index 18d059f0..9e9efedc 100644 --- a/.github/workflows/pandora-ci.yml +++ b/.github/workflows/pandora-ci.yml @@ -39,7 +39,7 @@ jobs: fail-fast: false max-parallel: 10 matrix: - godot-version: ["4.2.2", "4.3"] + godot-version: ["4.3"] name: "🤖 CI on Godot ${{ matrix.godot-version }}" steps: diff --git a/addons/gdUnit4/bin/GdUnitCmdTool.gd b/addons/gdUnit4/bin/GdUnitCmdTool.gd index 07d0926b..e540a5ec 100644 --- a/addons/gdUnit4/bin/GdUnitCmdTool.gd +++ b/addons/gdUnit4/bin/GdUnitCmdTool.gd @@ -397,7 +397,7 @@ class CLIRunner: var skipped := config.skipped() if skipped.is_empty(): return - _console.prints_warning("Found excluded test suite's configured at '%s'" % _runner_config_file) + for test_suite in test_suites: # skipp c# testsuites for now if test_suite.get_script() == null: @@ -407,23 +407,23 @@ class CLIRunner: # Dictionary[String, PackedStringArray] func skip_suite(test_suite: Node, skipped: Dictionary) -> void: - var skipped_suites :Array[String] = skipped.keys() + var skipped_suites :Array = skipped.keys() var suite_name := test_suite.get_name() var test_suite_path: String = ( test_suite.get_meta("ResourcePath") if test_suite.get_script() == null else test_suite.get_script().resource_path ) - for suite_to_skip in skipped_suites: + for suite_to_skip: String in skipped_suites: # if suite skipped by path or name if ( suite_to_skip == test_suite_path or (suite_to_skip.is_valid_filename() and suite_to_skip == suite_name) ): - var skipped_tests: Array[String] = skipped.get(suite_to_skip) - var skip_reason := "Excluded by config '%s'" % _runner_config_file + var skipped_tests: PackedStringArray = skipped.get(suite_to_skip) + var skip_reason := "Excluded by configuration" # if no tests skipped test the complete suite is skipped if skipped_tests.is_empty(): - _console.prints_warning("Mark test suite '%s' as skipped!" % suite_to_skip) + _console.prints_warning("Mark the entire test suite '%s' as skipped!" % test_suite_path) @warning_ignore("unsafe_property_access") test_suite.__is_skipped = true @warning_ignore("unsafe_property_access") diff --git a/addons/gdUnit4/plugin.cfg b/addons/gdUnit4/plugin.cfg index 6fdf5032..2070c972 100644 --- a/addons/gdUnit4/plugin.cfg +++ b/addons/gdUnit4/plugin.cfg @@ -3,5 +3,5 @@ name="gdUnit4" description="Unit Testing Framework for Godot Scripts" author="Mike Schulze" -version="4.4.1" +version="4.4.3" script="plugin.gd" diff --git a/addons/gdUnit4/src/asserts/GdAssertMessages.gd b/addons/gdUnit4/src/asserts/GdAssertMessages.gd index 83c2892c..2be8c117 100644 --- a/addons/gdUnit4/src/asserts/GdAssertMessages.gd +++ b/addons/gdUnit4/src/asserts/GdAssertMessages.gd @@ -179,10 +179,10 @@ static func test_timeout(timeout :int) -> String: static func test_suite_skipped(hint :String, skip_count :int) -> String: return """ %s - Tests skipped: %s + Skipped %s tests Reason: %s """.dedent().trim_prefix("\n")\ - % [_error("Entire test-suite is skipped!"), _colored_value(skip_count), _colored_value(hint)] + % [_error("The Entire test-suite is skipped!"), _colored_value(skip_count), _colored_value(hint)] static func test_skipped(hint :String) -> String: diff --git a/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd index b4a8038e..270119a6 100644 --- a/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd @@ -29,15 +29,19 @@ func _init(instance :Object, func_name :String, args := Array()) -> void: _current_value_provider = CallBackValueProvider.new(instance, func_name, args) -func _notification(_what :int) -> void: - if is_instance_valid(_current_value_provider): - _current_value_provider.dispose() - _current_value_provider = null - if is_instance_valid(_sleep_timer): - (Engine.get_main_loop() as SceneTree).root.remove_child(_sleep_timer) - _sleep_timer.stop() - _sleep_timer.free() - _sleep_timer = null +func _notification(what :int) -> void: + if what == NOTIFICATION_PREDELETE: + _interrupted = true + var main_node :Node = (Engine.get_main_loop() as SceneTree).root + if is_instance_valid(_current_value_provider): + _current_value_provider.dispose() + _current_value_provider = null + if is_instance_valid(_sleep_timer): + _sleep_timer.set_wait_time(0.0001) + _sleep_timer.stop() + main_node.remove_child(_sleep_timer) + _sleep_timer.free() + _sleep_timer = null func report_success() -> GdUnitFuncAssert: @@ -114,6 +118,10 @@ func cb_is_equal(c :Variant, e :Variant) -> bool: return GdObjects.equals(c,e) func cb_is_not_equal(c :Variant, e :Variant) -> bool: return not GdObjects.equals(c, e) +func do_interrupt() -> void: + _interrupted = true + + func _validate_callback(predicate :Callable, expected :Variant = null) -> void: if _interrupted: return @@ -125,9 +133,7 @@ func _validate_callback(predicate :Callable, expected :Variant = null) -> void: scene_tree.root.add_child(timer) timer.add_to_group("GdUnitTimers") @warning_ignore("return_value_discarded") - timer.timeout.connect(func do_interrupt() -> void: - _interrupted = true - , CONNECT_DEFERRED) + timer.timeout.connect(do_interrupt, CONNECT_DEFERRED) timer.set_one_shot(true) timer.start((_timeout/1000.0)*time_scale) _sleep_timer = Timer.new() diff --git a/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd index c3d5d5d6..7d4f57e4 100644 --- a/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd @@ -22,6 +22,14 @@ func _init(emitter :Object) -> void: GdAssertReports.reset_last_error_line_number() +func _notification(what :int) -> void: + if what == NOTIFICATION_PREDELETE: + _interrupted = true + if is_instance_valid(_emitter): + _signal_collector.unregister_emitter(_emitter) + _emitter = null + + func report_success() -> GdUnitAssert: GdAssertReports.report_success() return self diff --git a/addons/gdUnit4/src/core/GdArrayTools.gd b/addons/gdUnit4/src/core/GdArrayTools.gd index 19cbad0d..d4c7e8f2 100644 --- a/addons/gdUnit4/src/core/GdArrayTools.gd +++ b/addons/gdUnit4/src/core/GdArrayTools.gd @@ -93,6 +93,14 @@ static func as_string(elements: Variant, encode_value := true) -> String: return prefix + "[" + formatted + "]" +static func has_same_content(current: Array, other: Array) -> bool: + if current.size() != other.size(): return false + for element: Variant in current: + if not other.has(element): return false + if current.count(element) != other.count(element): return false + return true + + static func _typeof_as_string(value :Variant) -> String: var type := typeof(value) # for untyped array we retun empty string diff --git a/addons/gdUnit4/src/core/GdUnitFileAccess.gd b/addons/gdUnit4/src/core/GdUnitFileAccess.gd index e73216d0..cf8663c0 100644 --- a/addons/gdUnit4/src/core/GdUnitFileAccess.gd +++ b/addons/gdUnit4/src/core/GdUnitFileAccess.gd @@ -192,11 +192,12 @@ static func resource_as_string(resource_path :String) -> String: static func make_qualified_path(path :String) -> String: - if not path.begins_with("res://"): - if path.begins_with("//"): - return path.replace("//", "res://") - if path.begins_with("/"): - return "res:/" + path + if path.begins_with("res://"): + return path + if path.begins_with("//"): + return path.replace("//", "res://") + if path.begins_with("/"): + return "res:/" + path return path diff --git a/addons/gdUnit4/src/core/GdUnitSingleton.gd b/addons/gdUnit4/src/core/GdUnitSingleton.gd index 83a186f3..daa221c0 100644 --- a/addons/gdUnit4/src/core/GdUnitSingleton.gd +++ b/addons/gdUnit4/src/core/GdUnitSingleton.gd @@ -47,10 +47,10 @@ static func unregister(p_singleton :String, use_call_deferred :bool = false) -> static func dispose(use_call_deferred :bool = false) -> void: # use a copy because unregister is modify the singletons array - var singletons: PackedStringArray = Engine.get_meta(MEATA_KEY, PackedStringArray()) + var singletons :PackedStringArray = Engine.get_meta(MEATA_KEY, PackedStringArray()) GdUnitTools.prints_verbose("----------------------------------------------------------------") GdUnitTools.prints_verbose("Cleanup singletons %s" % singletons) - for singleton in singletons: + for singleton in PackedStringArray(singletons): unregister(singleton, use_call_deferred) Engine.remove_meta(MEATA_KEY) GdUnitTools.prints_verbose("----------------------------------------------------------------") diff --git a/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd b/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd index 438ddedf..c3e4d2c0 100644 --- a/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd +++ b/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd @@ -1,10 +1,36 @@ extends RefCounted + +# Caches all test indices for parameterized tests +class TestCaseIndicesCache: + var _cache := {} + + func _key(resource_path: String, test_name: String) -> StringName: + return &"%s_%s" % [resource_path, test_name] + + + func contains_test_case(resource_path: String, test_name: String) -> bool: + return _cache.has(_key(resource_path, test_name)) + + + func validate(resource_path: String, test_name: String, indices: PackedStringArray) -> bool: + var cached_indicies: PackedStringArray = _cache[_key(resource_path, test_name)] + return GdArrayTools.has_same_content(cached_indicies, indices) + + + func sync(resource_path: String, test_name: String, indices: PackedStringArray) -> void: + if indices.is_empty(): + _cache[_key(resource_path, test_name)] = [] + else: + _cache[_key(resource_path, test_name)] = indices + # contains all tracked test suites where discovered since editor start # key : test suite resource_path # value: the list of discovered test case names var _discover_cache := {} +var discovered_test_case_indices_cache := TestCaseIndicesCache.new() + func _init() -> void: # Register for discovery events to sync the cache @@ -12,11 +38,12 @@ func _init() -> void: GdUnitSignals.instance().gdunit_add_test_suite.connect(sync_cache) -func sync_cache(dto :GdUnitTestSuiteDto) -> void: +func sync_cache(dto: GdUnitTestSuiteDto) -> void: var resource_path := ProjectSettings.localize_path(dto.path()) - var discovered_test_cases :Array[String] = [] + var discovered_test_cases: Array[String] = [] for test_case in dto.test_cases(): discovered_test_cases.append(test_case.name()) + discovered_test_case_indices_cache.sync(resource_path, test_case.name(), test_case.test_case_names()) _discover_cache[resource_path] = discovered_test_cases @@ -54,6 +81,19 @@ func discover(script: Script) -> void: if not discovered_test_cases.has(test_case): tests_added.append(test_case) + # We need to scan for parameterized test because of possible test data changes + # For more details look at https://github.com/MikeSchulze/gdUnit4/issues/592 + for test_case_name in script_test_cases: + if discovered_test_case_indices_cache.contains_test_case(script_path, test_case_name): + var test_case: _TestCase = test_suite.find_child(test_case_name, false, false) + var test_indices := test_case.test_case_names() + if not discovered_test_case_indices_cache.validate(script_path, test_case_name, test_indices): + if !tests_removed.has(test_case_name): + tests_removed.append(test_case_name) + if !tests_added.has(test_case_name): + tests_added.append(test_case_name) + discovered_test_case_indices_cache.sync(script_path, test_case_name, test_indices) + # finally notify changes to the inspector if not tests_removed.is_empty() or not tests_added.is_empty(): # emit deleted tests @@ -68,6 +108,10 @@ func discover(script: Script) -> void: var dto := GdUnitTestCaseDto.new() dto = dto.deserialize(dto.serialize(test_case)) GdUnitSignals.instance().gdunit_event.emit(GdUnitEventTestDiscoverTestAdded.new(script_path, suite_name, dto)) + # if the parameterized test fresh added we need to sync the cache + if not discovered_test_case_indices_cache.contains_test_case(script_path, test_name): + discovered_test_case_indices_cache.sync(script_path, test_name, dto.test_case_names()) + # update the cache _discover_cache[script_path] = discovered_test_cases test_suite.queue_free() @@ -75,9 +119,16 @@ func discover(script: Script) -> void: func extract_test_functions(test_suite :Node) -> PackedStringArray: return test_suite.get_children()\ + .filter(func(child: Node) -> bool: return is_instance_of(child, _TestCase))\ .map(func (child: Node) -> String: return child.get_name()) +func is_paramaterized_test(test_suite :Node, test_case_name: String) -> bool: + return test_suite.get_children()\ + .filter(func(child: Node) -> bool: return child.name == test_case_name)\ + .any(func (test: _TestCase) -> bool: return test.is_parameterized()) + + # do rebuild the entire project, there is actual no way to enforce the Godot engine itself to do this func rebuild_project(script: Script) -> void: var class_path := ProjectSettings.globalize_path(script.resource_path) diff --git a/addons/gdUnit4/src/core/execution/GdUnitExecutionContext.gd b/addons/gdUnit4/src/core/execution/GdUnitExecutionContext.gd index 904da013..0e62682e 100644 --- a/addons/gdUnit4/src/core/execution/GdUnitExecutionContext.gd +++ b/addons/gdUnit4/src/core/execution/GdUnitExecutionContext.gd @@ -348,5 +348,7 @@ func register_auto_free(obj: Variant) -> Variant: ## Runs the gdunit garbage collector to free registered object func gc() -> void: + # unreference last used assert form the test to prevent memory leaks + GdUnitThreadManager.get_current_context().clear_assert() await _memory_observer.gc() orphan_monitor_stop() diff --git a/addons/gdUnit4/src/core/execution/stages/GdUnitTestCaseAfterStage.gd b/addons/gdUnit4/src/core/execution/stages/GdUnitTestCaseAfterStage.gd index 9b78f8a6..461fb137 100644 --- a/addons/gdUnit4/src/core/execution/stages/GdUnitTestCaseAfterStage.gd +++ b/addons/gdUnit4/src/core/execution/stages/GdUnitTestCaseAfterStage.gd @@ -17,8 +17,7 @@ func _execute(context: GdUnitExecutionContext) -> void: if _call_stage: @warning_ignore("redundant_await") await test_suite.after_test() - # unreference last used assert form the test to prevent memory leaks - GdUnitThreadManager.get_current_context().set_assert(null) + await context.gc() await context.error_monitor_stop() diff --git a/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteAfterStage.gd b/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteAfterStage.gd index 08bf3e56..a0f8ef19 100644 --- a/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteAfterStage.gd +++ b/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteAfterStage.gd @@ -12,8 +12,6 @@ func _execute(context :GdUnitExecutionContext) -> void: @warning_ignore("redundant_await") await test_suite.after() - # unreference last used assert form the test to prevent memory leaks - GdUnitThreadManager.get_current_context().set_assert(null) await context.gc() var reports := context.build_reports(false) fire_event(GdUnitEvent.new()\ diff --git a/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteExecutionStage.gd b/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteExecutionStage.gd index 5aad57d7..b62d27e0 100644 --- a/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteExecutionStage.gd +++ b/addons/gdUnit4/src/core/execution/stages/GdUnitTestSuiteExecutionStage.gd @@ -89,6 +89,19 @@ func fire_test_suite_skipped(context :GdUnitExecutionContext) -> void: var skip_count := test_suite.get_child_count() fire_event(GdUnitEvent.new()\ .suite_before(context.get_test_suite_path(), test_suite.get_name(), skip_count)) + + + for test_case_index in context.test_suite.get_child_count(): + # iterate only over test cases + var test_case := context.test_suite.get_child(test_case_index) as _TestCase + if not is_instance_valid(test_case): + continue + var test_case_context := GdUnitExecutionContext.of_test_case(context, test_case) + fire_event(GdUnitEvent.new()\ + .test_before(test_case_context.get_test_suite_path(), test_case_context.get_test_suite_name(), test_case_context.get_test_case_name())) + fire_test_skipped(test_case_context) + + var statistics := { GdUnitEvent.ORPHAN_NODES: 0, GdUnitEvent.ELAPSED_TIME: 0, @@ -105,6 +118,35 @@ func fire_test_suite_skipped(context :GdUnitExecutionContext) -> void: await (Engine.get_main_loop() as SceneTree).process_frame +func fire_test_skipped(context: GdUnitExecutionContext) -> void: + var test_case := context.test_case + var statistics := { + GdUnitEvent.ORPHAN_NODES: 0, + GdUnitEvent.ELAPSED_TIME: 0, + GdUnitEvent.WARNINGS: false, + GdUnitEvent.ERRORS: false, + GdUnitEvent.ERROR_COUNT: 0, + GdUnitEvent.FAILED: false, + GdUnitEvent.FAILED_COUNT: 0, + GdUnitEvent.SKIPPED: true, + GdUnitEvent.SKIPPED_COUNT: 1, + } + var report := GdUnitReport.new() \ + .create(GdUnitReport.SKIPPED, test_case.line_number(), GdAssertMessages.test_skipped("Skipped from the entire test suite")) + fire_event(GdUnitEvent.new() \ + .test_after(context.get_test_suite_path(), + context.get_test_suite_name(), + context.get_test_case_name(), + statistics, + [report])) + # finally fire test statistics report + fire_event(GdUnitEvent.new()\ + .test_statistics(context.get_test_suite_path(), + context.get_test_suite_name(), + context.get_test_case_name(), + statistics)) + + func set_debug_mode(debug_mode :bool = false) -> void: super.set_debug_mode(debug_mode) _stage_before.set_debug_mode(debug_mode) diff --git a/addons/gdUnit4/src/core/parse/GdScriptParser.gd b/addons/gdUnit4/src/core/parse/GdScriptParser.gd index bc300fff..d0a6e8ef 100644 --- a/addons/gdUnit4/src/core/parse/GdScriptParser.gd +++ b/addons/gdUnit4/src/core/parse/GdScriptParser.gd @@ -367,7 +367,7 @@ func get_function_descriptors(script: GDScript, included_functions: PackedString var func_name: String = method_descriptor["name"] if included_functions.is_empty() or func_name in included_functions: # exclude type set/geters - if func_name in ["@type_setter", "@type_getter"]: + if is_getter_or_setter(func_name): continue if not fds.any(func(fd: GdFunctionDescriptor) -> bool: return fd.name() == func_name): fds.append(GdFunctionDescriptor.extract_from(method_descriptor, false)) @@ -379,6 +379,10 @@ func get_function_descriptors(script: GDScript, included_functions: PackedString return fds +func is_getter_or_setter(func_name: String) -> bool: + return func_name.begins_with("@") and (func_name.ends_with("getter") or func_name.ends_with("setter")) + + func _parse_function_arguments(input: String) -> Dictionary: var arguments := {} var current_index := 0 diff --git a/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd index 8b4ae4ff..f2b2672c 100644 --- a/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd +++ b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd @@ -4,9 +4,9 @@ extends RefCounted var _thread :Thread var _thread_name :String var _thread_id :int -var _assert :GdUnitAssert var _signal_collector :GdUnitSignalCollector var _execution_context :GdUnitExecutionContext +var _asserts := [] func _init(thread :Thread = null) -> void: @@ -21,7 +21,7 @@ func _init(thread :Thread = null) -> void: func dispose() -> void: - _assert = null + clear_assert() if is_instance_valid(_signal_collector): _signal_collector.clear() _signal_collector = null @@ -29,12 +29,17 @@ func dispose() -> void: _thread = null +func clear_assert() -> void: + _asserts.clear() + + func set_assert(value :GdUnitAssert) -> void: - _assert = value + if value != null: + _asserts.append(value) func get_assert() -> GdUnitAssert: - return _assert + return null if _asserts.is_empty() else _asserts[-1] func set_execution_context(context :GdUnitExecutionContext) -> void: diff --git a/addons/gdUnit4/src/report/GdUnitHtmlPatterns.gd b/addons/gdUnit4/src/report/GdUnitHtmlPatterns.gd index 722c528f..a9da106c 100644 --- a/addons/gdUnit4/src/report/GdUnitHtmlPatterns.gd +++ b/addons/gdUnit4/src/report/GdUnitHtmlPatterns.gd @@ -13,6 +13,7 @@ const TABLE_RECORD_TESTSUITE = """ ${duration}
+
@@ -35,6 +36,7 @@ const TABLE_RECORD_PATH = """ ${duration}
+
@@ -95,6 +97,8 @@ const DURATION = "${duration}" const FAILURE_REPORT = "${failure-report}" const SUCCESS_PERCENT = "${success_percent}" + +const QUICK_STATE_SKIPPED = "${skipped-percent}" const QUICK_STATE_PASSED = "${passed-percent}" const QUICK_STATE_FLAKY = "${flaky-percent}" const QUICK_STATE_ERROR = "${error-percent}" @@ -128,6 +132,7 @@ static func build(template: String, report: GdUnitReportSummary, report_link: St .replace(SUCCESS_PERCENT, report.calculate_succes_rate(report.test_count(), report.error_count(), report.failure_count()))\ .replace(REPORT_STATE, report.report_state().to_lower())\ .replace(REPORT_STATE_LABEL, report.report_state())\ + .replace(QUICK_STATE_SKIPPED, calculate_percentage(report.test_count(), report.skipped_count()))\ .replace(QUICK_STATE_PASSED, calculate_percentage(report.test_count(), report.success_count()))\ .replace(QUICK_STATE_FLAKY, calculate_percentage(report.test_count(), report.flaky_count()))\ .replace(QUICK_STATE_ERROR, calculate_percentage(report.test_count(), report.error_count()))\ diff --git a/addons/gdUnit4/src/report/GdUnitReportSummary.gd b/addons/gdUnit4/src/report/GdUnitReportSummary.gd index e702491e..20a24e7a 100644 --- a/addons/gdUnit4/src/report/GdUnitReportSummary.gd +++ b/addons/gdUnit4/src/report/GdUnitReportSummary.gd @@ -59,7 +59,7 @@ func test_executed_count() -> int: func success_count() -> int: - return test_count() - error_count() - failure_count() - flaky_count() + return test_count() - error_count() - failure_count() - flaky_count() - skipped_count() func error_count() -> int: @@ -95,14 +95,16 @@ func add_report(report :GdUnitReportSummary) -> void: func report_state() -> String: - return calculate_state(error_count(), failure_count(), orphan_count(), flaky_count()) + return calculate_state(error_count(), failure_count(), orphan_count(), flaky_count(), skipped_count()) func succes_rate() -> String: return calculate_succes_rate(test_count(), error_count(), failure_count()) -func calculate_state(p_error_count :int, p_failure_count :int, p_orphan_count :int, p_flaky_count: int) -> String: +func calculate_state(p_error_count :int, p_failure_count :int, p_orphan_count :int, p_flaky_count: int, p_skipped_count: int) -> String: + if p_skipped_count > 0: + return "SKIPPED" if p_error_count > 0: return "ERROR" if p_failure_count > 0: diff --git a/addons/gdUnit4/src/report/template/css/styles.css b/addons/gdUnit4/src/report/template/css/styles.css index 23eac48e..e92d59b7 100644 --- a/addons/gdUnit4/src/report/template/css/styles.css +++ b/addons/gdUnit4/src/report/template/css/styles.css @@ -330,6 +330,10 @@ th.report-column { transition: width 0.3s ease; } +.status-skipped { + background-color: #888888; +} + .status-passed { background-color: #63bb38; } @@ -385,8 +389,7 @@ div.include-footer { } footer { - position: fixed; - padding-left: 10em; + position: static; left: 0; bottom: 0; width: 100%; @@ -399,6 +402,10 @@ footer { align-items: center; } +footer p { + padding-left: 10em; +} + footer .status-legend { display: flex; gap: 15px; diff --git a/addons/gdUnit4/src/report/template/folder_report.html b/addons/gdUnit4/src/report/template/folder_report.html index c6df9810..2cdca675 100644 --- a/addons/gdUnit4/src/report/template/folder_report.html +++ b/addons/gdUnit4/src/report/template/folder_report.html @@ -97,6 +97,9 @@

Report by Paths