baldertest 0.1.0b6__py3-none-any.whl → 0.1.0b8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87,21 +87,21 @@ class BasicExecutor(ABC):
87
87
  # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
88
88
 
89
89
  @abstractmethod
90
- def _prepare_execution(self):
90
+ def _prepare_execution(self, show_discarded):
91
91
  """
92
92
  This method runs before the branch will be executed and before the fixture construction code of this branch
93
93
  runs.
94
94
  """
95
95
 
96
96
  @abstractmethod
97
- def _body_execution(self):
97
+ def _body_execution(self, show_discarded):
98
98
  """
99
99
  This method runs between the fixture construction and teardown code. It should trigger the execution of the
100
100
  child branches.
101
101
  """
102
102
 
103
103
  @abstractmethod
104
- def _cleanup_execution(self):
104
+ def _cleanup_execution(self, show_discarded):
105
105
  """
106
106
  This method runs after the branch was executed (also after the fixture teardown code ran)
107
107
  """
@@ -137,17 +137,28 @@ class BasicExecutor(ABC):
137
137
  if isinstance(cur_child_executor.body_result, TestcaseResult):
138
138
  cur_child_executor.body_result.set_result(result=value, exception=None)
139
139
 
140
- def has_runnable_elements(self) -> bool:
140
+ def has_runnable_tests(self, consider_discarded_too=False) -> bool:
141
141
  """
142
142
  This method returns true if this executor element is runnable. The method returns true if this element has
143
143
  `prev_mark=RUNNABLE` and minimum one of its children has `prev_mark=RUNNABLE` too.
144
+
145
+ :param consider_discarded_too: True if the method allows DISCARDED elements too
144
146
  """
145
- if self.prev_mark != PreviousExecutorMark.RUNNABLE:
147
+ allowed_prev_marks = [PreviousExecutorMark.RUNNABLE]
148
+
149
+ if consider_discarded_too:
150
+ allowed_prev_marks.append(PreviousExecutorMark.DISCARDED)
151
+
152
+ if self.prev_mark not in allowed_prev_marks:
146
153
  return False
147
- for cur_child in self.all_child_executors:
148
- if cur_child.prev_mark == PreviousExecutorMark.RUNNABLE:
149
- return True
150
- return False
154
+
155
+ if self.all_child_executors is not None:
156
+ # the executor has child executors -> check them
157
+ for cur_child in self.all_child_executors:
158
+ if cur_child.has_runnable_tests(consider_discarded_too):
159
+ return True
160
+ return False
161
+ return True
151
162
 
152
163
  def get_all_base_instances_of_this_branch(
153
164
  self, with_type: Union[Type[Setup], Type[Scenario], Type[types.FunctionType]],
@@ -165,7 +176,7 @@ class BasicExecutor(ABC):
165
176
  # only go through cur_executor == ExecutorTree (do not iterate with this object)
166
177
  while cur_executor.parent_executor is not None:
167
178
  if isinstance(cur_executor.base_instance, with_type):
168
- if not only_runnable_elements or cur_executor.has_runnable_elements():
179
+ if not only_runnable_elements or cur_executor.has_runnable_tests():
169
180
  return [cur_executor.base_instance]
170
181
  cur_executor = cur_executor.parent_executor
171
182
 
@@ -181,10 +192,12 @@ class BasicExecutor(ABC):
181
192
  return list(set(result))
182
193
 
183
194
  @abstractmethod
184
- def cleanup_empty_executor_branches(self):
195
+ def cleanup_empty_executor_branches(self, consider_discarded=False):
185
196
  """
186
197
  This method searches the whole tree and removes branches where an executor item has no own children. It can
187
198
  remove these branches, because they have no valid matchings.
199
+
200
+ :param consider_discarded: true if this method should consider discarded branches, otherwise False
188
201
  """
189
202
 
190
203
  def filter_tree_for_user_filters(self):
@@ -221,32 +234,34 @@ class BasicExecutor(ABC):
221
234
  summary[cur_key] = cur_child_dict[cur_key]
222
235
  return summary
223
236
 
224
- def execute(self):
237
+ def execute(self, show_discarded=False):
225
238
  """
226
239
  Executes the whole branch
227
240
  """
228
241
  start_time = time.perf_counter()
229
- self._prepare_execution()
242
+ self._prepare_execution(show_discarded=show_discarded)
230
243
 
231
244
  try:
232
245
  try:
233
- self.fixture_manager.enter(self)
234
- self.construct_result.set_result(ResultState.SUCCESS)
246
+ if self.has_runnable_tests():
247
+ self.fixture_manager.enter(self)
248
+ self.construct_result.set_result(ResultState.SUCCESS)
235
249
 
236
- self._body_execution()
250
+ self._body_execution(show_discarded=show_discarded)
237
251
  except Exception as exc:
238
252
  # this has to be a construction fixture error
239
253
  traceback.print_exception(*sys.exc_info())
240
254
  self.construct_result.set_result(ResultState.ERROR, exc)
241
255
  finally:
242
- if self.fixture_manager.is_allowed_to_leave(self):
243
- self.fixture_manager.leave(self)
244
- self.teardown_result.set_result(ResultState.SUCCESS)
256
+ if self.has_runnable_tests():
257
+ if self.fixture_manager.is_allowed_to_leave(self):
258
+ self.fixture_manager.leave(self)
259
+ self.teardown_result.set_result(ResultState.SUCCESS)
245
260
  except Exception as exc:
246
261
  # this has to be a teardown fixture error
247
262
  traceback.print_exception(*sys.exc_info())
248
263
  self.teardown_result.set_result(ResultState.ERROR, exc)
249
264
 
250
- self._cleanup_execution()
265
+ self._cleanup_execution(show_discarded=show_discarded)
251
266
 
252
267
  self.execution_time_sec = time.perf_counter() - start_time
@@ -18,6 +18,7 @@ class ExecutorTree(BasicExecutor):
18
18
  """
19
19
  This class is the root object of the executor tree structure
20
20
  """
21
+ LINE_LENGTH = 120
21
22
 
22
23
  def __init__(self, fixture_manager: FixtureManager):
23
24
  super().__init__()
@@ -35,18 +36,13 @@ class ExecutorTree(BasicExecutor):
35
36
 
36
37
  @property
37
38
  def all_child_executors(self) -> List[BasicExecutor]:
38
- return self.setup_executors
39
+ return self._setup_executors
39
40
 
40
41
  @property
41
42
  def base_instance(self) -> object:
42
43
  """returns None because this element is a ExecutorTree"""
43
44
  return None
44
45
 
45
- @property
46
- def setup_executors(self) -> List[SetupExecutor]:
47
- """returns all setup executors of this tree"""
48
- return self._setup_executors
49
-
50
46
  @property
51
47
  def fixture_manager(self) -> FixtureManager:
52
48
  """returns the fixture manager of this tree"""
@@ -58,13 +54,13 @@ class ExecutorTree(BasicExecutor):
58
54
 
59
55
  # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
60
56
 
61
- def _prepare_execution(self):
57
+ def _prepare_execution(self, show_discarded):
62
58
  pass
63
59
 
64
- def _body_execution(self):
65
- for cur_setup_executor in self.setup_executors:
66
- if cur_setup_executor.has_runnable_elements():
67
- cur_setup_executor.execute()
60
+ def _body_execution(self, show_discarded):
61
+ for cur_setup_executor in self.get_setup_executors():
62
+ if cur_setup_executor.has_runnable_tests(consider_discarded_too=show_discarded):
63
+ cur_setup_executor.execute(show_discarded=show_discarded)
68
64
  elif cur_setup_executor.prev_mark == PreviousExecutorMark.SKIP:
69
65
  cur_setup_executor.set_result_for_whole_branch(ResultState.SKIP)
70
66
  elif cur_setup_executor.prev_mark == PreviousExecutorMark.COVERED_BY:
@@ -72,27 +68,31 @@ class ExecutorTree(BasicExecutor):
72
68
  else:
73
69
  cur_setup_executor.set_result_for_whole_branch(ResultState.NOT_RUN)
74
70
 
75
- def _cleanup_execution(self):
71
+ def _cleanup_execution(self, show_discarded):
76
72
  pass
77
73
 
78
74
  # ---------------------------------- METHODS -----------------------------------------------------------------------
79
75
 
76
+ def get_setup_executors(self) -> List[SetupExecutor]:
77
+ """returns all setup executors of this tree"""
78
+ return self._setup_executors
79
+
80
80
  def get_all_scenario_executors(self) -> List[ScenarioExecutor]:
81
81
  """
82
82
  returns a list with all scenario executors
83
83
  """
84
84
  all_scenario_executor = []
85
- for cur_setup_executor in self.setup_executors:
86
- all_scenario_executor += cur_setup_executor.scenario_executors
85
+ for cur_setup_executor in self.get_setup_executors():
86
+ all_scenario_executor += cur_setup_executor.get_scenario_executors()
87
87
  return all_scenario_executor
88
88
 
89
- def get_all_variation_executors(self) -> List[VariationExecutor]:
89
+ def get_all_variation_executors(self, return_discarded=False) -> List[VariationExecutor]:
90
90
  """
91
91
  returns a list with all variation executors
92
92
  """
93
93
  all_variation_executor = []
94
94
  for cur_scenario_executor in self.get_all_scenario_executors():
95
- all_variation_executor += cur_scenario_executor.variation_executors
95
+ all_variation_executor += cur_scenario_executor.get_variation_executors(return_discarded=return_discarded)
96
96
  return all_variation_executor
97
97
 
98
98
  def get_all_testcase_executors(self) -> List[TestcaseExecutor]:
@@ -101,8 +101,8 @@ class ExecutorTree(BasicExecutor):
101
101
  """
102
102
  all_testcase_executor = []
103
103
  for cur_scenario_executor in self.get_all_scenario_executors():
104
- for cur_variation_executor in cur_scenario_executor.variation_executors:
105
- all_testcase_executor += cur_variation_executor.testcase_executors
104
+ for cur_variation_executor in cur_scenario_executor.get_variation_executors():
105
+ all_testcase_executor += cur_variation_executor.get_testcase_executors()
106
106
  return all_testcase_executor
107
107
 
108
108
  def add_setup_executor(self, setup_executor: SetupExecutor):
@@ -129,35 +129,35 @@ class ExecutorTree(BasicExecutor):
129
129
  # can not find some
130
130
  return None
131
131
 
132
- def cleanup_empty_executor_branches(self):
132
+ def cleanup_empty_executor_branches(self, consider_discarded=False):
133
133
  to_remove_executor = []
134
- for cur_setup_executor in self.setup_executors:
135
- cur_setup_executor.cleanup_empty_executor_branches()
136
- if len(cur_setup_executor.scenario_executors) == 0:
134
+ for cur_setup_executor in self.get_setup_executors():
135
+ cur_setup_executor.cleanup_empty_executor_branches(consider_discarded=consider_discarded)
136
+ if len(cur_setup_executor.get_scenario_executors()) == 0:
137
137
  # remove this whole executor because it has no children anymore
138
138
  to_remove_executor.append(cur_setup_executor)
139
139
  for cur_setup_executor in to_remove_executor:
140
140
  self._setup_executors.remove(cur_setup_executor)
141
141
 
142
- def execute(self) -> None:
142
+ def execute(self, show_discarded=False) -> None:
143
143
  """
144
144
  This method executes this branch of the tree
145
145
  """
146
146
  start_text = "START TESTSESSION"
147
147
  end_text = "FINISH TESTSESSION"
148
- line_length = 120
149
148
 
150
149
  def print_line(text):
151
- full_text = int((line_length - (len(start_text) + 2)) / 2) * "=" + " " + text + " "
152
- full_text += "=" * (line_length - len(full_text))
150
+ full_text = int((self.LINE_LENGTH - (len(start_text) + 2)) / 2) * "=" + " " + text + " "
151
+ full_text += "=" * (self.LINE_LENGTH - len(full_text))
153
152
  print(full_text)
154
153
 
155
154
  print_line(start_text)
156
155
  # check if there exists runnable elements
157
- runnables = [cur_exec.has_runnable_elements() for cur_exec in self.setup_executors]
156
+ runnables = [cur_exec.has_runnable_tests(consider_discarded_too=show_discarded)
157
+ for cur_exec in self.get_setup_executors()]
158
158
  one_or_more_runnable_setups = None if len(runnables) == 0 else max(runnables)
159
159
  if one_or_more_runnable_setups:
160
- super().execute()
160
+ super().execute(show_discarded=show_discarded)
161
161
  else:
162
162
  print("NO EXECUTABLE SETUPS/SCENARIOS FOUND")
163
163
  print_line(end_text)
@@ -171,19 +171,32 @@ class ExecutorTree(BasicExecutor):
171
171
  print(f"TOTAL {cur_key.value}: {cur_val}", end="")
172
172
  print("")
173
173
 
174
- def print_tree(self) -> None:
174
+ def print_tree(self, show_discarded=False) -> None:
175
175
  """this method is an auxiliary method which outputs the entire tree"""
176
176
  print("RESOLVING OVERVIEW", end="\n\n")
177
- for cur_setup_executor in self.setup_executors:
178
- for cur_scenario_executor in cur_setup_executor.scenario_executors:
179
- for cur_variation_executor in cur_scenario_executor.variation_executors:
180
- print(f"Scenario `{cur_scenario_executor.base_scenario_class.__class__.__qualname__}` <-> "
177
+ for cur_setup_executor in self.get_setup_executors():
178
+ for cur_scenario_executor in cur_setup_executor.get_scenario_executors():
179
+ for cur_variation_executor in cur_scenario_executor.get_variation_executors(
180
+ return_discarded=show_discarded):
181
+ applicable = cur_variation_executor.prev_mark != PreviousExecutorMark.DISCARDED
182
+ start_char = '+' if applicable else 'X'
183
+ print(start_char * self.LINE_LENGTH)
184
+ applicability_str = "[APPLICABLE]" if applicable else "[DISCARDED] "
185
+ print(f"{start_char} {applicability_str} Scenario "
186
+ f"`{cur_scenario_executor.base_scenario_class.__class__.__qualname__}` <-> "
181
187
  f"Setup `{cur_setup_executor.base_setup_class.__class__.__qualname__}`")
182
188
  mapping_printings = {}
183
189
  for cur_scenario_device, cur_setup_device in cur_variation_executor.base_device_mapping.items():
184
190
  mapping_printings[f" {cur_scenario_device.__qualname__}"] = str(cur_setup_device.__qualname__)
185
191
  max_len = max(len(cur_elem) for cur_elem in mapping_printings.keys())
186
192
  for cur_key, cur_val in mapping_printings.items():
187
- print(("{:<" + str(max_len) + "} = {}").format(cur_key, cur_val))
188
- for cur_testcase_excutor in cur_variation_executor.testcase_executors:
189
- print(f" -> Testcase<{cur_testcase_excutor.base_testcase_callable.__qualname__}>")
193
+ print(("{} {:<" + str(max_len) + "} = {}").format(start_char, cur_key, cur_val))
194
+ for cur_testcase_excutor in cur_variation_executor.get_testcase_executors():
195
+ print(f"{start_char} -> Testcase<"
196
+ f"{cur_testcase_excutor.base_testcase_callable.__qualname__}>")
197
+ if cur_variation_executor.prev_mark == PreviousExecutorMark.DISCARDED:
198
+ print(f"{start_char}")
199
+ print(f"{start_char} DISCARDED BECAUSE "
200
+ f"`{cur_variation_executor.not_applicable_variation_exc.args[0]}`")
201
+ print(('+' if applicable else 'X') * self.LINE_LENGTH)
202
+ print('')
@@ -46,7 +46,7 @@ class ScenarioExecutor(BasicExecutor):
46
46
 
47
47
  @property
48
48
  def all_child_executors(self) -> List[VariationExecutor]:
49
- return self.variation_executors
49
+ return self._variation_executors
50
50
 
51
51
  @property
52
52
  def parent_executor(self) -> SetupExecutor:
@@ -64,11 +64,6 @@ class ScenarioExecutor(BasicExecutor):
64
64
  """returns the :class:`Scenario` class that belongs to this executor"""
65
65
  return self._base_scenario_class
66
66
 
67
- @property
68
- def variation_executors(self) -> List[VariationExecutor]:
69
- """returns all variation executors that are child executor of this scenario executor"""
70
- return self._variation_executors
71
-
72
67
  @property
73
68
  def fixture_manager(self) -> FixtureManager:
74
69
  """returns the current active fixture manager that belongs to this scenario executor"""
@@ -91,13 +86,13 @@ class ScenarioExecutor(BasicExecutor):
91
86
 
92
87
  # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
93
88
 
94
- def _prepare_execution(self):
89
+ def _prepare_execution(self, show_discarded):
95
90
  print(f" SCENARIO {self.base_scenario_class.__class__.__name__}")
96
91
 
97
- def _body_execution(self):
98
- for cur_variation_executor in self.variation_executors:
99
- if cur_variation_executor.has_runnable_elements():
100
- cur_variation_executor.execute()
92
+ def _body_execution(self, show_discarded):
93
+ for cur_variation_executor in self.get_variation_executors(return_discarded=show_discarded):
94
+ if cur_variation_executor.has_runnable_tests(show_discarded):
95
+ cur_variation_executor.execute(show_discarded=show_discarded)
101
96
  elif cur_variation_executor.prev_mark == PreviousExecutorMark.SKIP:
102
97
  cur_variation_executor.set_result_for_whole_branch(ResultState.SKIP)
103
98
  elif cur_variation_executor.prev_mark == PreviousExecutorMark.COVERED_BY:
@@ -105,18 +100,29 @@ class ScenarioExecutor(BasicExecutor):
105
100
  else:
106
101
  cur_variation_executor.set_result_for_whole_branch(ResultState.NOT_RUN)
107
102
 
108
- def _cleanup_execution(self):
103
+ def _cleanup_execution(self, show_discarded):
109
104
  pass
110
105
 
111
106
  # ---------------------------------- METHODS -----------------------------------------------------------------------
112
107
 
113
- def cleanup_empty_executor_branches(self):
108
+ def get_variation_executors(self, return_discarded=False) -> List[VariationExecutor]:
109
+ """
110
+ :param return_discarded: True if the method should return discarded variations too
111
+
112
+ :return: returns all variation executors that are child executor of this scenario executor
113
+ """
114
+ if not return_discarded:
115
+ return [cur_executor for cur_executor in self._variation_executors
116
+ if cur_executor.prev_mark != PreviousExecutorMark.DISCARDED]
117
+ return self._variation_executors
118
+
119
+ def cleanup_empty_executor_branches(self, consider_discarded=False):
114
120
  """
115
121
  This method removes all sub executors that are empty and not relevant anymore.
116
122
  """
117
123
  to_remove_executor = []
118
- for cur_variation_executor in self.variation_executors:
119
- if len(cur_variation_executor.testcase_executors) == 0:
124
+ for cur_variation_executor in self.get_variation_executors(return_discarded=consider_discarded):
125
+ if len(cur_variation_executor.get_testcase_executors()) == 0:
120
126
  # remove this whole executor because it has no children anymore
121
127
  to_remove_executor.append(cur_variation_executor)
122
128
  for cur_variation_executor in to_remove_executor:
@@ -42,7 +42,7 @@ class SetupExecutor(BasicExecutor):
42
42
 
43
43
  @property
44
44
  def all_child_executors(self) -> List[ScenarioExecutor]:
45
- return self.scenario_executors
45
+ return self._scenario_executors
46
46
 
47
47
  @property
48
48
  def parent_executor(self) -> ExecutorTree:
@@ -58,11 +58,6 @@ class SetupExecutor(BasicExecutor):
58
58
  """returns the base :class:`Setup` that belongs to this executor"""
59
59
  return self._base_setup_class
60
60
 
61
- @property
62
- def scenario_executors(self) -> List[ScenarioExecutor]:
63
- """returns a list with all scenario executors that belongs to this setup executor"""
64
- return self._scenario_executors
65
-
66
61
  @property
67
62
  def fixture_manager(self) -> FixtureManager:
68
63
  """returns the current active fixture manager for this executor"""
@@ -70,13 +65,13 @@ class SetupExecutor(BasicExecutor):
70
65
 
71
66
  # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
72
67
 
73
- def _prepare_execution(self):
68
+ def _prepare_execution(self, show_discarded):
74
69
  print(f"SETUP {self.base_setup_class.__class__.__name__}")
75
70
 
76
- def _body_execution(self):
77
- for cur_scenario_executor in self.scenario_executors:
78
- if cur_scenario_executor.has_runnable_elements():
79
- cur_scenario_executor.execute()
71
+ def _body_execution(self, show_discarded):
72
+ for cur_scenario_executor in self.get_scenario_executors():
73
+ if cur_scenario_executor.has_runnable_tests(consider_discarded_too=show_discarded):
74
+ cur_scenario_executor.execute(show_discarded=show_discarded)
80
75
  elif cur_scenario_executor.prev_mark == PreviousExecutorMark.SKIP:
81
76
  cur_scenario_executor.set_result_for_whole_branch(ResultState.SKIP)
82
77
  elif cur_scenario_executor.prev_mark == PreviousExecutorMark.COVERED_BY:
@@ -84,16 +79,20 @@ class SetupExecutor(BasicExecutor):
84
79
  else:
85
80
  cur_scenario_executor.set_result_for_whole_branch(ResultState.NOT_RUN)
86
81
 
87
- def _cleanup_execution(self):
82
+ def _cleanup_execution(self, show_discarded):
88
83
  pass
89
84
 
90
85
  # ---------------------------------- METHODS -----------------------------------------------------------------------
91
86
 
92
- def cleanup_empty_executor_branches(self):
87
+ def get_scenario_executors(self) -> List[ScenarioExecutor]:
88
+ """returns a list with all scenario executors that belongs to this setup executor"""
89
+ return self._scenario_executors
90
+
91
+ def cleanup_empty_executor_branches(self, consider_discarded=False):
93
92
  to_remove_executor = []
94
- for cur_scenario_executor in self.scenario_executors:
95
- cur_scenario_executor.cleanup_empty_executor_branches()
96
- if len(cur_scenario_executor.variation_executors) == 0:
93
+ for cur_scenario_executor in self.get_scenario_executors():
94
+ cur_scenario_executor.cleanup_empty_executor_branches(consider_discarded=consider_discarded)
95
+ if len(cur_scenario_executor.get_variation_executors(return_discarded=consider_discarded)) == 0:
97
96
  # remove this whole executor because it has no children anymore
98
97
  to_remove_executor.append(cur_scenario_executor)
99
98
  for cur_scenario_executor in to_remove_executor:
@@ -7,7 +7,6 @@ import traceback
7
7
  from _balder.utils import inspect_method
8
8
  from _balder.testresult import ResultState, TestcaseResult
9
9
  from _balder.executor.basic_executor import BasicExecutor
10
- from _balder.previous_executor_mark import PreviousExecutorMark
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from _balder.executor.variation_executor import VariationExecutor
@@ -76,7 +75,7 @@ class TestcaseExecutor(BasicExecutor):
76
75
 
77
76
  # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
78
77
 
79
- def _prepare_execution(self):
78
+ def _prepare_execution(self, show_discarded):
80
79
  print(f" TEST {self.base_testcase_callable.__qualname__} ", end='')
81
80
  if self.should_be_skipped():
82
81
  self.body_result.set_result(ResultState.SKIP)
@@ -84,7 +83,7 @@ class TestcaseExecutor(BasicExecutor):
84
83
  print("[S]")
85
84
  return
86
85
 
87
- def _body_execution(self):
86
+ def _body_execution(self, show_discarded):
88
87
  start_time = time.perf_counter()
89
88
  try:
90
89
  _, func_type = inspect_method(self.base_testcase_callable)
@@ -109,14 +108,11 @@ class TestcaseExecutor(BasicExecutor):
109
108
  self.body_result.set_result(ResultState.FAILURE, exc)
110
109
  self.test_execution_time_sec = time.perf_counter() - start_time
111
110
 
112
- def _cleanup_execution(self):
111
+ def _cleanup_execution(self, show_discarded):
113
112
  print(f"[{self.body_result.get_result_as_char()}]")
114
113
 
115
114
  # ---------------------------------- METHODS -----------------------------------------------------------------------
116
115
 
117
- def has_runnable_elements(self) -> bool:
118
- return self.prev_mark == PreviousExecutorMark.RUNNABLE
119
-
120
116
  def should_run(self):
121
117
  """returns true if the testcase should be executed (defined in scenario)"""
122
118
  if self.base_testcase_callable in self.parent_executor.parent_executor.all_run_tests:
@@ -135,7 +131,7 @@ class TestcaseExecutor(BasicExecutor):
135
131
  return True
136
132
  return False
137
133
 
138
- def cleanup_empty_executor_branches(self):
134
+ def cleanup_empty_executor_branches(self, consider_discarded=False):
139
135
  """
140
136
  This method searches the whole tree and removes branches where an executor item has no own children. It can
141
137
  remove these branches, because they have no valid matchings.