diff --git a/src/_balder/executor/basic_executable_executor.py b/src/_balder/executor/basic_executable_executor.py index 4a800119..3ab30be5 100644 --- a/src/_balder/executor/basic_executable_executor.py +++ b/src/_balder/executor/basic_executable_executor.py @@ -92,8 +92,9 @@ def filter_tree_for_user_filters(self): """ This method calls all user defined filters that are to be applied to the executor tree. """ - for cur_child_executor in self.all_child_executors: - cur_child_executor.filter_tree_for_user_filters() + if self.all_child_executors: + for cur_child_executor in self.all_child_executors: + cur_child_executor.filter_tree_for_user_filters() def execute(self, show_discarded=False): """ diff --git a/src/_balder/executor/basic_executor.py b/src/_balder/executor/basic_executor.py index 1624424b..eebdc993 100644 --- a/src/_balder/executor/basic_executor.py +++ b/src/_balder/executor/basic_executor.py @@ -38,7 +38,7 @@ def __init__(self): @property @abstractmethod - def all_child_executors(self) -> List[BasicExecutor]: + def all_child_executors(self) -> list[BasicExecutor] | None: """ returns all child executors of this object or None if no child executors can exist (this element is a leaf) """ @@ -185,8 +185,9 @@ def filter_tree_for_user_filters(self): """ This method calls all user defined filters that are to be applied to the executor tree. """ - for cur_child_executor in self.all_child_executors: - cur_child_executor.filter_tree_for_user_filters() + if self.all_child_executors: + for cur_child_executor in self.all_child_executors: + cur_child_executor.filter_tree_for_user_filters() def testsummary(self) -> ResultSummary: """ @@ -198,7 +199,7 @@ def testsummary(self) -> ResultSummary: if isinstance(self.body_result, TestcaseResult): setattr(summary, self.executor_result.value, 1) - else: + elif self.all_child_executors: for cur_child_exec in self.all_child_executors: summary += cur_child_exec.testsummary() return summary diff --git a/src/_balder/executor/executor_tree.py b/src/_balder/executor/executor_tree.py index 524c2673..977e0262 100644 --- a/src/_balder/executor/executor_tree.py +++ b/src/_balder/executor/executor_tree.py @@ -38,7 +38,7 @@ def __init__(self, fixture_manager: FixtureManager): # ---------------------------------- PROPERTIES -------------------------------------------------------------------- @property - def all_child_executors(self) -> List[BasicExecutableExecutor]: + def all_child_executors(self) -> List[BasicExecutableExecutor] | None: return self._setup_executors @property diff --git a/src/_balder/executor/unresolved_parametrized_testcase_executor.py b/src/_balder/executor/unresolved_parametrized_testcase_executor.py index b6827138..91a4ccca 100644 --- a/src/_balder/executor/unresolved_parametrized_testcase_executor.py +++ b/src/_balder/executor/unresolved_parametrized_testcase_executor.py @@ -37,9 +37,6 @@ def __init__( # holds the specific static parameters for this unresolved group self._static_parameters = static_parameters if static_parameters is not None else {} - # holds the dynamically created testcase executors as soon as this executor is entered - self._testcase_executors = None - # contains the result object for the BODY part of this branch self.body_result = BranchBodyResult(self) @@ -53,8 +50,8 @@ def base_testcase_callable(self) -> callable: return self._base_testcase_callable @property - def all_child_executors(self) -> List[ParametrizedTestcaseExecutor]: - return self.get_testcase_executors() + def all_child_executors(self) -> None: + return None @property def base_testcase_obj(self) -> Scenario: @@ -69,24 +66,6 @@ def base_instance(self) -> object: returns the base class instance to which this executor instance belongs""" return self._base_testcase_callable - @property - def parametrization_has_been_resolved(self) -> bool: - """returns true if the parametrization has been resolved""" - return self._testcase_executors is not None - - def has_runnable_tests(self, consider_discarded_too=False) -> bool: - if self.parametrization_has_been_resolved: - return super().has_runnable_tests(consider_discarded_too=consider_discarded_too) - - allowed_prev_marks = [PreviousExecutorMark.RUNNABLE] - - if consider_discarded_too: - allowed_prev_marks.append(PreviousExecutorMark.DISCARDED) - - if self.prev_mark not in allowed_prev_marks: - return False - return True - def has_skipped_tests(self) -> bool: return self.prev_mark == PreviousExecutorMark.SKIP @@ -117,29 +96,27 @@ def get_covered_by_element(self) -> List[Scenario | callable]: all_covered_by_data.extend(covered_by_dict.get(None, [])) return all_covered_by_data - def get_testcase_executors(self) -> List[ParametrizedTestcaseExecutor | UnresolvedParametrizedTestcaseExecutor]: - """returns all sub testcase executors that belongs to this variation-executor""" - if self._testcase_executors is None: - return [self] - return self._testcase_executors - - def resolve_dynamic_parametrization(self): + def get_resolved_parametrized_testcase_executors(self): """ resolves the dynamic parametrization - should be called when setup features are active in the scenario """ - self._testcase_executors = [] + executors = [] parametrization = self.get_parametrization() - if parametrization: - for cur_parametrization in parametrization: - self._testcase_executors.append( - ParametrizedTestcaseExecutor( - self._base_testcase_callable, - parent=self.parent_executor, - parametrization=cur_parametrization, - unresolved_group_obj=self - ) + + if not parametrization: + return [] + + for cur_parametrization in parametrization: + executors.append( + ParametrizedTestcaseExecutor( + self._base_testcase_callable, + parent=self.parent_executor, + parametrization=cur_parametrization, + unresolved_group_obj=self ) + ) + return executors def get_parametrization(self) -> List[OrderedDict[str, Any]] | None: """ diff --git a/src/_balder/executor/variation_executor.py b/src/_balder/executor/variation_executor.py index 832d9774..6b3e41be 100644 --- a/src/_balder/executor/variation_executor.py +++ b/src/_balder/executor/variation_executor.py @@ -171,7 +171,7 @@ def _prepare_execution(self, show_discarded): self.exchange_unmapped_vdevice_references() self.update_vdevice_referenced_feature_instances() self.set_conn_dependent_methods() - self.resolve_possible_parametrization() + self.resolve_and_exchange_unresolved_parametrization() def _body_execution(self, show_discarded): if show_discarded and not self.can_be_applied(): @@ -332,16 +332,9 @@ def testsummary(self) -> ResultSummary: return super().testsummary() return ResultSummary() - def get_testcase_executors(self) -> List[TestcaseExecutor]: + def get_testcase_executors(self) -> List[TestcaseExecutor | UnresolvedParametrizedTestcaseExecutor]: """returns all sub testcase executors that belongs to this variation-executor""" - result = [] - for cur_executor in self._testcase_executors: - if (isinstance(cur_executor, UnresolvedParametrizedTestcaseExecutor) and - cur_executor.parametrization_has_been_resolved): - result += cur_executor.get_testcase_executors() - else: - result.append(cur_executor) - return result + return self._testcase_executors.copy() def add_testcase_executor(self, testcase_executor: TestcaseExecutor | UnresolvedParametrizedTestcaseExecutor): """ @@ -878,8 +871,12 @@ def set_conn_dependent_methods(self): cur_setup_feature_controller.set_active_method_variation(method_selection=method_var_selection) - def resolve_possible_parametrization(self): + def resolve_and_exchange_unresolved_parametrization(self): """resolves the parametrization if there are any :class:`UnresolvedParametrizedTestcaseExecutor` in the tree""" + replaced_executors = [] for cur_child in self._testcase_executors: if isinstance(cur_child, UnresolvedParametrizedTestcaseExecutor): - cur_child.resolve_dynamic_parametrization() + replaced_executors.extend(cur_child.get_resolved_parametrized_testcase_executors()) + else: + replaced_executors.append(cur_child) + self._testcase_executors = replaced_executors diff --git a/src/_balder/testresult.py b/src/_balder/testresult.py index 4020372c..48873b57 100644 --- a/src/_balder/testresult.py +++ b/src/_balder/testresult.py @@ -106,9 +106,10 @@ def result(self): """returns the determined result for the inner branch of the related executor""" relative_result = ResultState.NOT_RUN priority_order = ResultState.priority_order() - for cur_child in self._related_executor.all_child_executors: - if priority_order.index(cur_child.executor_result) < priority_order.index(relative_result): - relative_result = cur_child.executor_result + if self._related_executor.all_child_executors: + for cur_child in self._related_executor.all_child_executors: + if priority_order.index(cur_child.executor_result) < priority_order.index(relative_result): + relative_result = cur_child.executor_result self._result = relative_result return self._result diff --git a/tests/parametrization/test_1_dynamic_parametrizing_no_iterable/test_1_dynamic_parametrizing_no_iterable.py b/tests/parametrization/test_1_dynamic_parametrizing_no_iterable/test_1_dynamic_parametrizing_no_iterable.py index 5d733f01..0aad1ae0 100644 --- a/tests/parametrization/test_1_dynamic_parametrizing_no_iterable/test_1_dynamic_parametrizing_no_iterable.py +++ b/tests/parametrization/test_1_dynamic_parametrizing_no_iterable/test_1_dynamic_parametrizing_no_iterable.py @@ -52,6 +52,8 @@ def processed(env_dir): all_variation_executor = all_scenario_executor[0].get_variation_executors() + assert len(all_variation_executor) == 1, f"detect more than one variation executor" + assert all_variation_executor[0].executor_result == ResultState.NOT_RUN, \ "the variation executor does not have result SUCCESS" @@ -60,7 +62,13 @@ def processed(env_dir): assert all_variation_executor[0].teardown_result.result == ResultState.NOT_RUN all_testcase_executor = all_variation_executor[0].get_testcase_executors() - assert len(all_testcase_executor) == 0, f"detect some testcase executor" + assert len(all_testcase_executor) == 1, f"detect some testcase executor" + assert isinstance(all_testcase_executor[0], UnresolvedParametrizedTestcaseExecutor), \ + f"test case executor is from unexpected type {type(all_testcase_executor[0])}" + + assert all_testcase_executor[0].construct_result.result == ResultState.NOT_RUN + assert all_testcase_executor[0].body_result.result == ResultState.NOT_RUN + assert all_testcase_executor[0].teardown_result.result == ResultState.NOT_RUN exceptions = all_scenario_executor[0].get_all_recognized_exception() assert len(exceptions) == 1, f"detect more than one exception executor"