Migrates the remaining test items to the ParamSet/Param declaration
introduced in d0721af:
- dialogs: image, question, value, choices, tested_references
- actions: check, run, report
- console: parent + open/read_until actions
- py_func / lua_func
- containers: group, parallel + parallel_branch, unittest
- complex: cycle (sub-block exit_condition documented in
EXIT_CONDITION_PARAMS), git
- runtime_plot: parent + open/close/periodic/last_value actions
- json_rpc: parent + query/receive actions
Items intentionally without PARAMS (and therefore not validated) are
those whose body is the unstructured user value: console write/writeln,
plot add/export, and the json_rpc/console open & close actions. Same
for the internally-instantiated TestItemUnittestElement which passes
dict_item=None.
Behavior on valid .tum files is unchanged (validation suite source
mode: SUCCESS). Typos on declared params now surface as warnings
listing the accepted names; missing required params surface as load-
time errors with file context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
2.6 KiB
Python
70 lines
2.6 KiB
Python
from interpreter.test_items.test_item import (TestItem, test_run)
|
|
from interpreter.test_items.test_result import (TestResult, TestValue)
|
|
from interpreter.utils.constants import TestItemType as cst
|
|
from interpreter.utils.param_decl import ParamSet
|
|
from runtime.tum_except import ETUMSyntaxError
|
|
import api.testium as tm
|
|
|
|
class TestItemGroup(TestItem):
|
|
|
|
# 'group' has no item-specific parameters; 'steps' is handled by COMMON_PARAMS.
|
|
# Declaring an empty ParamSet still opts in to unknown-param validation
|
|
# (e.g. typo 'stop_on_failures').
|
|
PARAMS = ParamSet()
|
|
|
|
def __init__(self, dict_cycle, parent = None, status_queue=None, filename=""):
|
|
self._name = cst.TYPE_GROUP.item_name
|
|
super().__init__(dict_cycle, parent, status_queue, filename=filename)
|
|
self._type = cst.TYPE_GROUP
|
|
self.is_container = True
|
|
|
|
def __runALoop(self):
|
|
results = []
|
|
i = 0
|
|
to_be_stopped = False
|
|
while (not self.isStopped()) and (i < self.childCount()) and (not to_be_stopped):
|
|
result = self.child(i).execute()
|
|
results.append(result)
|
|
if result.test_result == TestValue.FAILURE and self._stop_on_failure:
|
|
to_be_stopped = True
|
|
i = i + 1
|
|
|
|
if self.isStopped() or to_be_stopped:
|
|
for j in range(self.childCount()):
|
|
if self.child(j).executedOnStop() and (j >= i):
|
|
self.child(j).execute()
|
|
|
|
test_success = TestValue.SUCCESS
|
|
for res in results:
|
|
if res.test_result == TestValue.FAILURE:
|
|
test_success = TestValue.FAILURE
|
|
break
|
|
|
|
result = TestResult(None, test_success, 'Group iteration')
|
|
return result
|
|
|
|
@test_run
|
|
def execute(self):
|
|
results = []
|
|
to_be_stopped = False
|
|
if (not self.isStopped()) and (not to_be_stopped):
|
|
result = self.__runALoop()
|
|
|
|
# Test results
|
|
results.append(result)
|
|
|
|
if result.test_result == TestValue.FAILURE and self._stop_on_failure:
|
|
to_be_stopped = True
|
|
|
|
# end of loop test
|
|
if self.isStopped() or to_be_stopped:
|
|
if to_be_stopped:
|
|
self.result.set(TestValue.FAILURE, 'Group execution aborted on failure')
|
|
else:
|
|
self.result.set(TestValue.NORUN, 'Group execution aborted on user request')
|
|
else:
|
|
self.result.set(TestValue.SUCCESS, '')
|
|
for res in results:
|
|
if not res.success:
|
|
self.result.set(TestValue.FAILURE, '')
|