1 Commits

Author SHA1 Message Date
9dae210f7f fix(windows): UTF-8 console + self-sufficient validation wrapper
Make the suite run cleanly on Windows.

Product code:
- __init__.py: force UTF-8 on stdout/stderr. The Windows console code
  page (cp1252) cannot encode the box-drawing/accented characters the
  runner prints, which crashed the parent capture_stdout thread. Only
  the stream encoders are reconfigured; the locale default used to read
  cp1252 config files is left untouched.
- report_export_junit/html: open the report file with encoding="utf-8"
  (XML/HTML are UTF-8) instead of the platform default, matching the
  txt/json exporters.

Validation:
- run.bat: source mode now sets up its own venv and runs testium from
  src\ directly instead of delegating to the project run.bat (which
  launches the GUI and drops its arguments). Installs the fake_exporter
  entry-point plugin (report_plugin) and the [lsp] extra, and runs the
  same lsp_check.py pre-flight as run.sh.
- jsonrpc/test.tum: launch the echo server via "$(python_bin)" instead
  of "python3" (the Microsoft Store stub on Windows).
- post_execution.py: write the JUnit XML with encoding="utf-8".
- restore items/run/sub_pass.tum and sub_fail.tum, deleted by mistake in
  d97d00c "removed test logs".
2026-06-06 21:39:36 +02:00
22 changed files with 198 additions and 321 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,6 +11,16 @@ 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 = float(self._prms.getParam("timeout", default=-1, processed=True)) read_timeout = int(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') as f: with open(self._file_name, 'w', encoding="utf-8") 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') as f: with open(self._file_name, 'w', encoding="utf-8") as f:
TestSuite.to_file(f, [ts]) TestSuite.to_file(f, [ts])
def testsIterate(self, row): def testsIterate(self, row):

View File

@@ -56,17 +56,9 @@ function handle.func_call(params)
if err == nil then if err == nil then
print(string.format("Function executed from '%s'", pfile)) print(string.format("Function executed from '%s'", pfile))
utils.log("func_call function found '%s', '%s'", file, fname) utils.log("func_call function found '%s', '%s'", file, fname)
err_res = {pcall(func, unpack(prms))} succ, ret = pcall(func, unpack(prms))
utils.log("func_call returned '%s', '%s'", tostring(succ), tostring(ret)) utils.log("func_call returned '%s', '%s'", tostring(succ), tostring(ret))
-- manage tuple ouput of a lua function
succ = table.remove(err_res, 1)
if #err_res > 1 then
ret = err_res
else
ret = unpack(err_res)
end
if succ then if succ then
res = ret res = ret
else else

View File

@@ -51,18 +51,14 @@ 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 \ if self.load(file_name) and w.test_service is not None:
w.test_service is not None and \ if w.treeTests.getItemCount() == previous_count:
w.treeTests.getItemCount() == previous_count: w.treeTests.restoreCheckList(previous_check_list, w.test_service)
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,18 +84,7 @@
- read_until: {expected: HelloConsole, timeout: 1, mute: true} - read_until: {expected: HelloConsole, timeout: 1, mute: true}
- console: - console:
name: Console read_until float timeout name: Console read_until muted
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: python3 {{include_directory}}/jrpc_echo_server.py -c {{include_directory}}/jrpces.ini - writeln: '"$(python_bin)" {{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

@@ -12,12 +12,12 @@ function module.assertparam(param)
end end
function module.checkglobal(param) function module.checkglobal(param)
assert(param=='test parameter') local res = tm.gd(param)
return 0 return res
end end
function module.checkglobal2(index) function module.checkglobal2(index)
return tm.gd("data_to_be_returned")[index+1] return tm.gd("lua_data_to_be_returned")[index]
end end
function module.should_not_be_called(param) function module.should_not_be_called(param)
@@ -53,7 +53,7 @@ function module.return_nothing()
-- Returns no value: ret is nil but no error. -- Returns no value: ret is nil but no error.
end end
function module.return_explicit_none() function module.return_explicit_nil()
return nil return nil
end end

View File

@@ -1,6 +1,6 @@
skipped_test_item: ['skipped_checkglobal'] skipped_test_item: ['skipped_checkglobal']
data_to_be_returned: lua_data_to_be_returned:
- 1 - 1
- {a: 1, b: 2} - {a: 1, b: 2}
- ["a", 1, 2.1, True] - ["a", 1, 2.1, True]

View File

@@ -1,15 +1,7 @@
- let: - let:
name: lua_func test constants, name: lua_func test constants,
values: values:
- func_test_parameter: test parameter lua_func test parameter: test parameter lua_func
- lua_func:
name: pass lua_func
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: assertparam
param:
- true
- lua_func: - lua_func:
name: fail lua_func name: fail lua_func
@@ -20,7 +12,7 @@
- false - false
- lua_func: - lua_func:
name: fail lua_func with expected result "FAIL" name: fail lua_func with expected result FAIL
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: assertparam func_name: assertparam
@@ -70,7 +62,35 @@
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal func_name: checkglobal
param: param:
- $(func_test_parameter) - lua_func test parameter
expected_result: $(lua_func test parameter)
- lua_func:
name: global param lua_func 1
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 1
expected_result: ($(lua_data_to_be_returned))[0]
- lua_func:
name: global param lua_func 2
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 2
expected_result: ($(lua_data_to_be_returned))[1]
- lua_func:
name: global param lua_func 3
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 3
expected_result: ($(lua_data_to_be_returned))[2]
- let: - let:
name: python2func name: python2func
@@ -78,189 +98,88 @@
values: values:
- py: $(test_path)$(psep)lua_func.lua - py: $(test_path)$(psep)lua_func.lua
- lua_func:
name: global param int
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 0
expected_result: ($(data_to_be_returned))[0]
- lua_func:
name: global param dict
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 1
expected_result: ($(data_to_be_returned))[1]
- lua_func:
name: global param list
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: checkglobal2
param:
- 2
expected_result: ($(data_to_be_returned))[2]
- lua_func:
name: global param lua_func
key: $(test)_PASS
file: $(py)
func_name: checkglobal
param:
- $(func_test_parameter)
- lua_func: - lua_func:
name: skipped_checkglobal name: skipped_checkglobal
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: should_not_be_called func_name: should_not_be_called
param: param:
- $(func_test_parameter) - $(test parameter)
- lua_func: - lua_func:
name: skipped true name: skipped true
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: checkglobal
skipped: true skipped: true
param: param:
- "skipped" - $(test parameter)
- lua_func: - lua_func:
name: skipped 1 name: skipped 1
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: checkglobal
skipped: 1 skipped: 1
param: param:
- "skipped" - $(test parameter)
- group: - group:
name: Function results check name: Function results check
steps: steps:
- group: - group:
name: Functions result name: Function result failure
steps: steps:
- lua_func: - lua_func:
name: int name: int failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [-1] param: [-1]
- lua_func: - lua_func:
name: float name: float failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [-20.3] param: [-1.3]
- lua_func: - lua_func:
name: String name: String failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [ "FAIL" ] param: [ "FAIL" ]
- lua_func: - lua_func:
name: Tuple int,str name: Tuple int,str failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: tuple_return func_name: tuple_return
param: [ 0, "OK" ] param: [ -1, "Got a failure" ]
- group: - group:
name: Functions result expected name: Functions result success
steps: steps:
- lua_func: - lua_func:
name: int expected name: int success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [18] param: [0]
expected_result: 18
- lua_func: - lua_func:
name: float expected name: float success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [0.3] param: [0.3]
expected_result: 0.3
- lua_func: - lua_func:
name: String expected name: String success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: echo func_name: echo
param: [ "Something" ] param: [ "Something that is not only strictly FAIL" ]
expected_result: Something
- lua_func: - lua_func:
name: Tuple int,str expected name: Tuple int,str success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: tuple_return func_name: tuple_return
param: [ 0, "OK" ] param: [ 0, "OK" ]
expected_result: [0, "OK"]
- lua_func:
name: small list expected
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [ [-23] ]
expected_result: [-23]
- lua_func:
name: big list expected
key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [ [-23, 17, 67] ]
expected_result: [-23, 17, 67]
- group:
name: Function result not expected
steps:
- lua_func:
name: int not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [18]
expected_result: 17
- lua_func:
name: float not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [0.3]
expected_result: 0.5
- lua_func:
name: String not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [ "Something" ]
expected_result: Nothing
- lua_func:
name: Tuple int,str not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: tuple_return
param: [ 0, "OK" ]
expected_result: [0, "OUPS"]
- lua_func:
name: small list not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [ [-23] ]
expected_result: [-22]
- lua_func:
name: big list not expected
key: $(test)_FAIL
file: $(test_path)$(psep)lua_func.lua
func_name: echo
param: [ [-23, 17, 67] ]
expected_result: [-23, 16, 67]
- lua_func: - lua_func:
name: delgd test name: delgd test
key: $(test)_PASS key: $(test)_PASS
@@ -274,39 +193,40 @@
func_name: return_nothing func_name: return_nothing
- lua_func: - lua_func:
name: function returning explicit None should succeed name: function returning explicit nil should succeed
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: return_explicit_none func_name: return_explicit_nil
- group: - group:
name: context_id tests name: context_id tests
steps: steps:
- lua_func: - lua_func:
name: set serializable value name: set context value
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: set_context_value func_name: set_context_value
context_id: lua_ctx_test
param: param:
- hello context - hello lua
expected_result: hello context expected_result: hello lua
- lua_func: - lua_func:
name: get serializable value (same context_id) name: get context value (same context_id)
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: get_context_value func_name: get_context_value
context_id: ctx_test context_id: lua_ctx_test
expected_result: hello context expected_result: hello lua
- lua_func: - lua_func:
name: get serializable value (no context_id, from main gd) name: get context value (no context_id, from main gd)
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: get_context_value func_name: get_context_value
expected_result: hello context expected_result: hello lua
- lua_func: - lua_func:
name: get serializable value (different context_id) name: get context value (different context_id)
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)lua_func.lua file: $(test_path)$(psep)lua_func.lua
func_name: get_context_value func_name: get_context_value
context_id: ctx_other context_id: lua_ctx_other
expected_result: hello context expected_result: hello lua

View File

@@ -1,6 +1 @@
skipped_test_item: ['skipped_checkglobal'] skipped_test_item: ['skipped_checkglobal']
data_to_be_returned:
- 1
- {a: 1, b: 2}
- ["a", 1, 2.1, True]

View File

@@ -16,8 +16,8 @@ def checkglobal(param):
assert param=='test parameter' assert param=='test parameter'
return 0 return 0
def checkglobal2(index): def checkglobal2():
return tm.gd("data_to_be_returned")[index] return tm.gd("py_func test parameter")
def should_not_be_called(param): def should_not_be_called(param):
raise raise

View File

@@ -1,7 +1,7 @@
- let: - let:
name: py_func test constants, name: py_func test constants,
values: values:
- func_test_parameter: test parameter py_func test parameter: test parameter
- py_func: - py_func:
name: pass py_func name: pass py_func
@@ -70,7 +70,7 @@
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: checkglobal func_name: checkglobal
param: param:
- $(func_test_parameter) - $(py_func test parameter)
- let: - let:
name: python2func name: python2func
@@ -79,32 +79,11 @@
- py: $(test_path)$(psep)py_func.py - py: $(test_path)$(psep)py_func.py
- py_func: - py_func:
name: global param int name: global param py_func 2
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(py)
func_name: checkglobal2 func_name: checkglobal2
param: expected_result: $(py_func test parameter)
- 0
expected_result: ($(data_to_be_returned))[0]
- py_func:
name: global param dict
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py
func_name: checkglobal2
param:
- 1
expected_result: ($(data_to_be_returned))[1]
- py_func:
name: global param list
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py
func_name: checkglobal2
param:
- 2
expected_result: ($(data_to_be_returned))[2]
- py_func: - py_func:
@@ -113,162 +92,104 @@
file: $(py) file: $(py)
func_name: checkglobal func_name: checkglobal
param: param:
- $(func_test_parameter) - $(py_func test parameter)
- py_func: - py_func:
name: skipped_checkglobal name: skipped_checkglobal
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: should_not_be_called func_name: should_not_be_called
param: param:
- $(func_test_parameter) - $(py_func test parameter)
- py_func: - py_func:
name: skipped true name: skipped true
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: checkglobal
skipped: true skipped: true
param: param:
- "skipped" - $(py_func test parameter)
- py_func: - py_func:
name: skipped 1 name: skipped 1
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: checkglobal
skipped: 1 skipped: 1
param: param:
- "skipped" - $(py_func test parameter)
- py_func: - py_func:
name: FunctionItem test name: FunctionItem test
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: ValidationTest func_name: ValidationTest
param: param:
- $(func_test_parameter) - $(py_func test parameter)
- group: - group:
name: Function results check name: Function results check
steps: steps:
- group: - group:
name: Functions result name: Function result 1
steps: steps:
- py_func: - py_func:
name: int name: int failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [-1] param: [-1]
expected_result: -1
- py_func: - py_func:
name: float name: float failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [-20.3] param: [-1.3]
expected_result: -1.3
- py_func: - py_func:
name: String name: String failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [ "FAIL" ] param: [ "FAIL" ]
expected_result: FAIL
- py_func: - py_func:
name: Tuple int,str name: Tuple int,str failure
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: tuple_return func_name: tuple_return
param: [ 0, "OK" ] param: [ -1, "Got a failure" ]
expected_result: [-1, "Got a failure"]
- group: - group:
name: Functions result expected name: Functions result 2
steps: steps:
- py_func: - py_func:
name: int expected name: int success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [18] param: [0]
expected_result: 18 expected_result: 0
- py_func: - py_func:
name: float expected name: float success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [0.3] param: [0.3]
expected_result: 0.3 expected_result: 0.3
- py_func: - py_func:
name: String expected name: String success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: echo func_name: echo
param: [ "Something" ] param: [ "Something that is not only strictly FAIL" ]
expected_result: Something expected_result: Something that is not only strictly FAIL
- py_func: - py_func:
name: Tuple int,str expected name: Tuple int,str success
key: $(test)_PASS key: $(test)_PASS
file: $(test_path)$(psep)py_func.py file: $(test_path)$(psep)py_func.py
func_name: tuple_return func_name: tuple_return
param: [ 0, "OK" ] param: [ 0, "OK" ]
expected_result: [0, "OK"] expected_result: [0, "OK"]
- py_func:
name: small list expected
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [ [-23] ]
expected_result: [-23]
- py_func:
name: big list expected
key: $(test)_PASS
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [ [-23, 17, 67] ]
expected_result: [-23, 17, 67]
- group:
name: Function result not expected
steps:
- py_func:
name: int not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [18]
expected_result: 17
- py_func:
name: float not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [0.3]
expected_result: 0.5
- py_func:
name: String not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [ "Something" ]
expected_result: Nothing
- py_func:
name: Tuple int,str not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: tuple_return
param: [ 0, "OK" ]
expected_result: [0, "OUPS"]
- py_func:
name: small list not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [ [-23] ]
expected_result: [-22]
- py_func:
name: big list not expected
key: $(test)_FAIL
file: $(test_path)$(psep)py_func.py
func_name: echo
param: [ [-23, 17, 67] ]
expected_result: [-23, 16, 67]
- py_func: - py_func:
name: delgd test name: delgd test
key: $(test)_PASS key: $(test)_PASS

View File

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

View File

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

View File

@@ -31,11 +31,7 @@ main:
{% for item in items %} {% for item in items %}
# item test # item test
- let: - let: {name: {{ item }} test constants, values: {test: {{ item }}, test_path: items/$(test)}}
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") as f: with open(junit_report, "w", encoding="utf-8") as f:
f.write(TestSuite.to_xml_string([ts])) f.write(TestSuite.to_xml_string([ts]))
# cleanup # cleanup

View File

@@ -89,6 +89,13 @@ 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%
@@ -100,8 +107,25 @@ echo ERROR: unknown --mode '%MODE%'. Expected: source ^| wheel ^| pyinstaller.
exit /b 1 exit /b 1
:MODE_SOURCE :MODE_SOURCE
call "%PROJECT_DIR%\run.bat" %TAIL% REM Run testium from src\ in a dedicated venv set up here. We do NOT delegate to
exit /b %ERRORLEVEL% REM the project's run.bat: that one launches the GUI and does not forward its
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"
@@ -115,10 +139,13 @@ 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
call "%WHEEL_VENV%\Scripts\pip" install --quiet "%WHEEL%" REM install with the [lsp] extra so the wheel channel is validated in its
REM language-server-capable form (pulls pygls), matching `pip install testium[lsp]`.
call "%WHEEL_VENV%\Scripts\pip" install --quiet "%WHEEL%[lsp]"
) )
"%WHEEL_VENV%\Scripts\python.exe" -m testium %TAIL% call "%WHEEL_VENV%\Scripts\pip" install --quiet -e "%FAKE_EXPORTER%"
exit /b %ERRORLEVEL% SET CMD="%WHEEL_VENV%\Scripts\python.exe" -m testium
GOTO LAUNCH
:MODE_PYI :MODE_PYI
SET "PYI_BIN=%PROJECT_DIR%\dist\testium-%VERSION%.exe" SET "PYI_BIN=%PROJECT_DIR%\dist\testium-%VERSION%.exe"
@@ -127,5 +154,22 @@ 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
) )
"%PYI_BIN%" %TAIL% SET CMD="%PYI_BIN%"
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%