Skip to main content

run-tests

Run Embody's test suite and write new tests (Embody development)

Source facts

Repository
dylanroscover/Embody
Last source activity
September 5, 2026 at 02:56
Detected SKILL.md language
English
Stars
182
Forks
11

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
run-tests
description
Run Embody's test suite and write new tests (Embody development)
disable-model-invocation
true
# Test Suite Embody has 110+ test suites (2,500+ tests) under `dev/embody/unit_tests/` covering externalization, MCP tools, TDXN format, the Envoy server/bridge/jobs, install/upgrade paths, and infrastructure. Destructive and agent tiers are segregated behind their own entry points. ## The save gate (read this before a full run) `run_tests` **refuses a full run** when the saved `.toe` is missing or more than an hour old, and reports the recovery point's age on *every* run. Call `save_project` first; pass `confirm_saved=True` only to deliberately accept losing everything since the last save. A single suite (`suite_name=...`) is never gated -- gating cheap frequent runs would just train callers to pass the override reflexively. **Never gate on "is there unsaved work".** `project.dirty` does not exist on TD 2025 (a `getattr` guard silently read `None` and the check was off), and `project.modified` returns a LIST of operator paths -- not a bool -- that re-populates within seconds of a successful save. Both proxies have failed here, in opposite directions. The age of the `.toe` on disk is the only honest signal, which is what the gate and `RunDestructiveTests` both use. ## Running Tests **From TouchDesigner:** ```python op.unit_tests.RunTests() # All tests, one per frame op.unit_tests.RunTests(suite_name='test_path_utils') # Specific suite op.unit_tests.RunTests(suite_name='test_path_utils', test_name='test_normalizePath_backslashes_converted') op.unit_tests.RunTestsSync() # Synchronous (blocks TD) results = op.unit_tests.GetResults() # Get results dict ``` **Via MCP -- use the `run_tests` tool, NOT RunTestsSync inside execute_python:** ```python run_tests(background=True) # all suites -- RECOMMENDED for full runs get_job_status(job_id='job_...') # poll; the finished record carries the summary run_tests(suite_name='test_path_utils') # small targeted runs may stay synchronous ``` For a FULL run always pass `background=True`: it returns a job id immediately and results park restart-proof in `.embody/jobs/`. The synchronous mode holds the HTTP call open for the whole run, and the Envoy watchdog suites restart the very server it waits on -- the call is severed ("Server force-restarted / shutting down during test run") even though the run finishes. (Pre-job-layer fallback, still valid: poll `execute_python(code="result = op.unit_tests.GetResults()")` until the totals stop moving.) `RunTestsSync()` inside `execute_python` runs the whole suite INSIDE that dispatch's undo block: the undo-guard tests fail (a block is already open) and the entire run becomes one giant Ctrl+Z step. ## Writing New Tests Create a test file in `dev/embody/unit_tests/`: ```python """Test suite: description of what this tests.""" class TestMyFeature(EmbodyTestCase): def test_something(self): """Test description.""" op = self.sandbox.create(baseCOMP, 'test_op') result = self.embody_ext.someMethod(op) self.assertEqual(result, expected_value) self.assertTrue(op.valid) self.assertIn('foo', result) def setUp(self): pass def tearDown(self): super().tearDown() # Cleans up sandbox ``` **Key objects:** `self.sandbox` (temp baseCOMP), `self.embody` (op.Embody), `self.embody_ext` (op.Embody.ext.Embody), `self.runner` (TestRunnerExt). All TD globals available. ## Test Coverage Count suites with `ls dev/embody/unit_tests/test_*.py` -- the hand-maintained breakdown that used to sit here drifted 4x stale and was removed. Suite docstrings state their scope. ## After Running Tests Always read log files at `dev/logs/` - the ring buffer only holds 200 entries. Grep for `ERROR` and `WARNING`.
View on GitHub