Files
testium/src/testium/interpreter/test_items/test_item_group.py
François b1a7dac0f3 item params: migrate every structured item to declarative PARAMS
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>
2026-05-29 11:14:42 +02:00

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, '')