3 Commits

17 changed files with 44 additions and 93 deletions

View File

@@ -9,9 +9,9 @@ This element is of the following form:
- let: - let:
name: Let Item name: Let Item
values: values:
key1: value1 - key1: value1
key2: value2 - key2: value2
key3: <| $(variable)[$(loop_index)] |> - key3: <| $(variable)[$(loop_index)] |>
The ``let`` element is used to set values in the global directory. The ``let`` element is used to set values in the global directory.

View File

@@ -51,8 +51,8 @@ The parameter file can be specified in the `.tum` file root:
:caption: configuration files definition in the main `.tum` test file :caption: configuration files definition in the main `.tum` test file
config_file: config_file:
config1.yaml - config1.yaml
config2.yaml - config2.yaml
main: main:
name: Test example name: Test example

View File

@@ -11,16 +11,6 @@ sys.path.append(os.path.abspath(ourpath.parent))
import interpreter.utils.constants as cst import interpreter.utils.constants as cst
def main(): def main():
# Force UTF-8 on stdout/stderr so the runner's output survives a legacy
# console code page (Windows cp1252 can't encode box-drawing/accented
# chars). Only the stream encoders change; the locale default used for
# config files is untouched.
for _stream in (sys.stdout, sys.stderr):
try:
_stream.reconfigure(encoding="utf-8")
except (AttributeError, ValueError):
pass # no stdout (frozen GUI) or non-reconfigurable stream
# Subcommand dispatch (must run *before* argparse so neither 'schema' nor # Subcommand dispatch (must run *before* argparse so neither 'schema' nor
# 'lsp' has to share the GUI/batch flag surface). The subcommands also # 'lsp' has to share the GUI/batch flag surface). The subcommands also
# skip the multiprocessing 'spawn' setup which is only meaningful for the # skip the multiprocessing 'spawn' setup which is only meaningful for the

View File

@@ -344,7 +344,7 @@ class TestItemConsoleReadUntil(TestItemConsoleAction):
def execute(self): def execute(self):
cons = self.get_console() cons = self.get_console()
ru = self._prms.expanse(self._read_until) ru = self._prms.expanse(self._read_until)
read_timeout = int(self._prms.getParam("timeout", default=-1, processed=True)) read_timeout = float(self._prms.getParam("timeout", default=-1, processed=True))
mute = self._prms.getParam("mute", default=False, processed=True) mute = self._prms.getParam("mute", default=False, processed=True)
if read_timeout < 0: if read_timeout < 0:
read_timeout = None read_timeout = None

View File

@@ -14,7 +14,7 @@ class ReportExportHTML(rpe.ReportExport):
self.prepareFile() self.prepareFile()
self.create_base() self.create_base()
self.process_tests() self.process_tests()
with open(self._file_name, 'w', encoding="utf-8") as f: with open(self._file_name, 'w') as f:
f.write(lxml.html.tostring(self.root, pretty_print=True).decode()) f.write(lxml.html.tostring(self.root, pretty_print=True).decode())
def testsIterate(self, row): def testsIterate(self, row):

View File

@@ -20,7 +20,7 @@ class ReportExportJUnit(rpe.ReportExport):
ts = TestSuite(repname, test_cases=self.test_cases, ts = TestSuite(repname, test_cases=self.test_cases,
hostname=tm.gd('host_ip')) hostname=tm.gd('host_ip'))
with open(self._file_name, 'w', encoding="utf-8") as f: with open(self._file_name, 'w') as f:
TestSuite.to_file(f, [ts]) TestSuite.to_file(f, [ts])
def testsIterate(self, row): def testsIterate(self, row):

View File

@@ -51,14 +51,18 @@ class TestFileManager:
w.disconnect_signals() w.disconnect_signals()
# Snapshot user-selected checkboxes and fold state so they survive a # Snapshot user-selected checkboxes and fold state so they survive a
# reload of the same file (same logic as session-restore through prefs). # reload of the same file (same logic as session-restore through prefs).
# checkList works only if show_checkboxes is True
previous_check_list = w.treeTests.getCheckList() previous_check_list = w.treeTests.getCheckList()
previous_fold_list = w.treeTests.getFoldList() previous_fold_list = w.treeTests.getFoldList()
previous_count = w.treeTests.getItemCount() previous_count = w.treeTests.getItemCount()
self.clear_process() self.clear_process()
if self.load(file_name) and w.test_service is not None: if self.load(file_name) and \
if w.treeTests.getItemCount() == previous_count: w.test_service is not None and \
w.treeTests.restoreCheckList(previous_check_list, w.test_service) w.treeTests.getItemCount() == previous_count:
if prefs.settings.show_checkboxes :
w.treeTests.restoreCheckList(previous_check_list, w.test_service)
w.treeTests.restoreFoldList(previous_fold_list) w.treeTests.restoreFoldList(previous_fold_list)
w.reconnect_signals() w.reconnect_signals()
def _make_progress(self, w): def _make_progress(self, w):

View File

@@ -84,7 +84,18 @@
- read_until: {expected: HelloConsole, timeout: 1, mute: true} - read_until: {expected: HelloConsole, timeout: 1, mute: true}
- console: - console:
name: Console read_until muted name: Console read_until float timeout
console_name: term
key: $(test)_PASS
steps:
- writeln: echo "HelloConsole"
{% if os == "Windows" %}
- read_until: {expected: echo "HelloConsole", timeout: 0.2}
{% endif %}
- read_until: {expected: HelloConsole, timeout: 0.2}
- console:
name: Console read_until process result
console_name: term console_name: term
key: $(test)_PASS key: $(test)_PASS
steps: steps:

View File

@@ -20,7 +20,7 @@
console_name: jrpces console_name: jrpces
key: $(test)_PASS key: $(test)_PASS
steps: steps:
- writeln: '"$(python_bin)" {{include_directory}}/jrpc_echo_server.py -c {{include_directory}}/jrpces.ini' - writeln: python3 {{include_directory}}/jrpc_echo_server.py -c {{include_directory}}/jrpces.ini
- read_until: {expected: ready, timeout: 5} - read_until: {expected: ready, timeout: 5}
- console: - console:

View File

@@ -11,8 +11,8 @@
- let: - let:
name: Let it be name: Let it be
values: values:
it: $(loop_param) - it: $(loop_param)
be: <| $(loop_param) == $(it) |> - be: <| $(loop_param) == $(it) |>
- loop: - loop:
name: Cycle iterating on list name: Cycle iterating on list

View File

@@ -1,7 +1,7 @@
- let: - let:
name: lua_func test constants, name: lua_func test constants,
values: values:
lua_func test parameter: test parameter lua_func - lua_func test parameter: test parameter lua_func
- lua_func: - lua_func:
name: fail lua_func name: fail lua_func

View File

@@ -1,7 +1,7 @@
- let: - let:
name: py_func test constants, name: py_func test constants,
values: values:
py_func test parameter: test parameter - py_func test parameter: test parameter
- py_func: - py_func:
name: pass py_func name: pass py_func

View File

@@ -1,7 +0,0 @@
main:
name: run sub-test (always fail)
steps:
- check:
name: fail
values:
- false

View File

@@ -1,7 +0,0 @@
main:
name: run sub-test (always pass)
steps:
- check:
name: pass
values:
- true

View File

@@ -31,7 +31,11 @@ main:
{% for item in items %} {% for item in items %}
# item test # item test
- let: {name: {{ item }} test constants, values: {test: {{ item }}, test_path: items/$(test)}} - let:
name: {{ item }} test constants
values:
- test: {{ item }}
- test_path: items/$(test)
- group: - group:
name: {{ item }} test name: {{ item }} test
steps: steps:

View File

@@ -89,7 +89,7 @@ def exec():
junit_report = report.replace(".sqlite", f"-{test}.xml") junit_report = report.replace(".sqlite", f"-{test}.xml")
print(junit_report) print(junit_report)
_prepare_file_to_save(junit_report) _prepare_file_to_save(junit_report)
with open(junit_report, "w", encoding="utf-8") as f: with open(junit_report, "w") as f:
f.write(TestSuite.to_xml_string([ts])) f.write(TestSuite.to_xml_string([ts]))
# cleanup # cleanup

View File

@@ -89,13 +89,6 @@ REM Reports are stamped with the mode so successive runs don't clobber each othe
SET "TAIL=-b -d "python_bin=%VENV_PYTHON%" -d "validation_report_file=validation-%MODE%" -- "%SCRIPT_DIR%\main.tum"%EXTRA%" SET "TAIL=-b -d "python_bin=%VENV_PYTHON%" -d "validation_report_file=validation-%MODE%" -- "%SCRIPT_DIR%\main.tum"%EXTRA%"
REM The report-exporter plugin (items\report_plugin) is a pip entry-point
REM package. It must live in the *testium* environment, so it is installed into
REM the source/wheel venvs below. A frozen PyInstaller binary cannot see
REM externally-installed plugins, so report_plugin is expected to be skipped
REM there (same as Linux pyinstaller mode).
SET "FAKE_EXPORTER=%SCRIPT_DIR%\fake_exporter"
REM ---------- per-mode launcher ---------------------------------------------- REM ---------- per-mode launcher ----------------------------------------------
echo -- validation mode: %MODE% echo -- validation mode: %MODE%
@@ -107,25 +100,8 @@ echo ERROR: unknown --mode '%MODE%'. Expected: source ^| wheel ^| pyinstaller.
exit /b 1 exit /b 1
:MODE_SOURCE :MODE_SOURCE
REM Run testium from src\ in a dedicated venv set up here. We do NOT delegate to call "%PROJECT_DIR%\run.bat" %TAIL%
REM the project's run.bat: that one launches the GUI and does not forward its exit /b %ERRORLEVEL%
REM arguments, so the suite would never run head-less.
SET "TESTIUM_VENV=%PROJECT_DIR%\test\tmp\testium_venv"
IF NOT EXIST "%TESTIUM_VENV%" (
echo Creating testium venv at %TESTIUM_VENV%
%PYTHON_EXE% -m venv "%TESTIUM_VENV%"
IF !ERRORLEVEL! NEQ 0 (
echo ERROR while creating the testium venv.
exit /b 1
)
call "%TESTIUM_VENV%\Scripts\pip" install --quiet --upgrade pip
call "%TESTIUM_VENV%\Scripts\pip" install --quiet -r "%PROJECT_DIR%\src\requirements.txt"
REM language-server extra so `testium lsp` works from source (lsp_check.py)
call "%TESTIUM_VENV%\Scripts\pip" install --quiet "pygls>=1.3"
)
call "%TESTIUM_VENV%\Scripts\pip" install --quiet -e "%FAKE_EXPORTER%"
SET CMD="%TESTIUM_VENV%\Scripts\python.exe" "%PROJECT_DIR%\src\testium"
GOTO LAUNCH
:MODE_WHEEL :MODE_WHEEL
SET "WHEEL=%PROJECT_DIR%\dist\testium-%VERSION%-py3-none-any.whl" SET "WHEEL=%PROJECT_DIR%\dist\testium-%VERSION%-py3-none-any.whl"
@@ -139,13 +115,10 @@ IF NOT EXIST "%WHEEL_VENV%" (
echo Creating wheel venv at %WHEEL_VENV% echo Creating wheel venv at %WHEEL_VENV%
%PYTHON_EXE% -m venv --system-site-packages "%WHEEL_VENV%" %PYTHON_EXE% -m venv --system-site-packages "%WHEEL_VENV%"
call "%WHEEL_VENV%\Scripts\pip" install --quiet --upgrade pip call "%WHEEL_VENV%\Scripts\pip" install --quiet --upgrade pip
REM install with the [lsp] extra so the wheel channel is validated in its call "%WHEEL_VENV%\Scripts\pip" install --quiet "%WHEEL%"
REM language-server-capable form (pulls pygls), matching `pip install testium[lsp]`.
call "%WHEEL_VENV%\Scripts\pip" install --quiet "%WHEEL%[lsp]"
) )
call "%WHEEL_VENV%\Scripts\pip" install --quiet -e "%FAKE_EXPORTER%" "%WHEEL_VENV%\Scripts\python.exe" -m testium %TAIL%
SET CMD="%WHEEL_VENV%\Scripts\python.exe" -m testium exit /b %ERRORLEVEL%
GOTO LAUNCH
:MODE_PYI :MODE_PYI
SET "PYI_BIN=%PROJECT_DIR%\dist\testium-%VERSION%.exe" SET "PYI_BIN=%PROJECT_DIR%\dist\testium-%VERSION%.exe"
@@ -154,22 +127,5 @@ IF NOT EXIST "%PYI_BIN%" (
echo ERROR: PyInstaller binary not found in %PROJECT_DIR%\dist -- run build_all.sh first. echo ERROR: PyInstaller binary not found in %PROJECT_DIR%\dist -- run build_all.sh first.
exit /b 1 exit /b 1
) )
SET CMD="%PYI_BIN%" "%PYI_BIN%" %TAIL%
GOTO LAUNCH
REM ---------- launch ----------------------------------------------------------
:LAUNCH
echo -- launch: %CMD%
REM LSP check (this exact channel): `schema` must keep its nested actions and
REM `lsp` must answer initialize. Mirrors run.sh; aborts the run on failure.
echo -- LSP check (%MODE%)
"%VENV_PYTHON%" "%SCRIPT_DIR%\lsp_check.py" %CMD%
IF !ERRORLEVEL! NEQ 0 (
echo ERROR: LSP check failed for mode %MODE%.
exit /b 1
)
%CMD% %TAIL%
exit /b %ERRORLEVEL% exit /b %ERRORLEVEL%