7.0 KiB
Testium — Claude Context
What is testium
Testium is a test sequencer/runner written in Python. It executes YAML-based test scripts (".tum" files) and supports three execution modes:
- GUI mode (default, no flag): PySide6 Qt application (
src/testium/main_win/) - Batch mode (
-b/--batch-execution): headless, non-interactive, runs tests and exits - Terminal mode (
-m/--terminal): interactive REPL in the terminal (partially implemented / work-in-progress)
Run from repo root: ./run.sh (Linux) or run.bat / run.ps1 (Windows).
Direct invocation: python3 -m src/testium [-b|-m] <test_file.tum>
Architecture
Entry point
src/testium/__init__.py — parses CLI args, dispatches to the three modes.
multiprocessing.set_start_method('spawn') is called early (required for Linux dialog subprocesses).
Core execution
src/testium/interpreter/process.py—TestProcess(multiprocessing.Process): runs the test in a child process. Stdout is redirected via aStringQueue→ pipe → parent thread (capture_stdout) that writes to real stdout.src/testium/interpreter/batch.py—Batch: parent-side orchestrator for-bmode. Creates themsg_queue, startsTestProcess, waits for the "finished" signal.src/testium/interpreter/test_set.py—TestSet: builds and executes the tree of test items.src/testium/interpreter/test_items/test_item*.py— one file per test item type (check, cycle, group, let, unittest, py_func, lua_func, console, git, dialogs, report, …).
Communication channels (parent ↔ child process)
msg_queue(multiprocessing.Queue): carries status messages from child to parent.- Item status:
{"id": <non-None>, "name": ..., "status": "started"|"finished", ...} - Global dict updates:
{"type": "gd_update"|"gd_delete", "key": ..., "value": ...}— no "id" key - Process finished:
{"id": None, "name": "test_process", "status": "finished"}— id key present butNone
- Item status:
tst_ctrl(TestSetController): sends control commands (execute, stop, pause, close, …) from parent to child.- stdout pipe (
multiprocessing.Pipe): streams test output from child back to parent'scapture_stdoutthread.
Stdout pipeline (batch mode)
test item print()
→ sys.stdout (StringQueue, in child)
→ send_stdout thread (child) → pipe → capture_stdout thread (parent)
→ print() → sys.stdout (TermLog wrapping real stdout, in parent)
→ terminal
Global dictionary
src/testium/interpreter/utils/globdict.py — shared state accessible from test scripts via tm.gd() / tm.setgd(). When set_update_queue() is active (during test execution), every setgd/delgd on a non-_-prefixed key pushes a message to msg_queue.
Coloring (-o disables it)
src/testium/interpreter/utils/termlog.py — TermLog wraps stdout with colorama-based line coloring (PASS=green, FAIL=red, WARN=yellow, …). Applied in parent process for batch/terminal modes. Auto-detects light/dark terminal background via (in order): COLORFGBG env var, OSC 11 query, default dark.
Dialog items in batch mode
All dialog items (dialog_image, dialog_question, dialog_references, dialog_value, dialog_message, dialog_choices, dialog_note) follow this rule in non-interactive text mode (-b):
auto_resultdefined in the.tum→ result controlled by it (ok/yes→ SUCCESS,cancel/no→ FAIL)auto_resultabsent → FAIL with"Dialog not supported in batch mode"sleep dialog: true→ exception: just sleeps normally, no GUI, no failure
auto_result (and auto_value for value/note dialogs) is intended for the validation test suite (test/validation/) only.
Key files
| Path | Role |
|---|---|
src/testium/__init__.py |
CLI entry, mode dispatch |
src/testium/interpreter/batch.py |
-b mode orchestrator |
src/testium/interpreter/process.py |
Child test process |
src/testium/interpreter/terminal.py |
-m mode (WIP) |
src/testium/interpreter/test_set.py |
Test tree builder/executor |
src/testium/interpreter/utils/globdict.py |
Global variable dict |
src/testium/interpreter/utils/termlog.py |
Terminal color output |
src/lib/stdout_redirect.py |
StdioRedirect singleton (stdio_redir) |
src/lib/string_queue.py |
Thread-safe string buffer used for stdout redirection |
src/testium/libs/testium.py |
Public API for test scripts (tm.*) |
GUI icons (main_win)
Icons live in src/testium/main_win/resources/ with three theme variants:
| Folder | Theme index | Usage |
|---|---|---|
color/ |
0 (default) | Coloured icons |
black/ |
1 | Black silhouette on transparent |
white/ |
2 | White silhouette on transparent (LA mode) |
Icons are 64×64 PNG. Black variants: RGBA with RGB=(0,0,0), alpha varies. White variants: LA with luminance=255, alpha varies.
The mapping item-type → icon filename is in _ITEM_CONFIG (src/testium/main_win/test_tree_items/test_tree_item.py). At runtime, icon_prefix() returns :/color, :/black, or :/white (Qt resource prefix) based on the user preference.
All icons must be declared in src/testium/main_win/resources/testium_core_win.qrc (one entry per theme section). After any QRC change, regenerate the compiled resource file:
cd src/testium/main_win/resources
pyside6-rcc testium_core_win.qrc -o testium_core_win_rc.py
Icons are assigned once when the test file is loaded (not updated live on theme change — a file reload is required).
Known issues / WIP
-m(terminal mode) is not functional yet.
run item
src/testium/interpreter/test_items/test_item_run.py — launches a .tum file in a new testium instance (-b in batch mode, -r in GUI mode). Result:
- SUCCESS if the sub-instance launched and ran to completion (exit code is ignored)
- FAILURE if the file is not found,
wait_for_execis set withoutstart_time/end_time, the time window was not reached, or any other launch error
The sub-test's own pass/fail result is intentionally not propagated.
Recent fixes (branch text_no_pyside)
batch.py: premature loop exit whengd_updatemessages (no"id"key) were mistaken for the "finished" signal — fix:"id" in m and m["id"] is Nonebatch.py:control("loaded")deadlock ifTestProcesscrashed beforecmd_thstarted — fix: daemon thread +threading.Event+is_alive()pollingtermlog.py:COLOR_DEFAULT = Fore.WHITEinvisible on light terminals; added auto-detection + light palette. Also fixedwrite()residue accumulation bug (s[pos:]→s[pos+1:]).- Dialog items:
auto_result/auto_valuenow used in non-interactive text mode; dialogs withoutauto_resultFAIL immediately in batch mode. runitem: removedstdout=PIPE(caused deadlock withmultiprocessingspawn); simplified result to SUCCESS on any completed subprocess.
Validation tests
Located in test/validation/. Run with -b flag against each .tum file.
Dependencies
See src/requirements.txt. Key ones: pyside6, pyyaml, jinja2, colorama, gitpython, pexpect, matplotlib.