BlockedError → blocked, never fail). Your test files stay exactly as they are.
Installation
The framework adoption layer is an optional extra:Three adoption tiers
Adopt incrementally — each tier works on its own, and none requires changing your test files.1
Tier 1 — Import your existing results
Keep your current runner. Import its JUnit XML or Robot See
output.xml so history, trends, and MCP querying work before any rig integration:crucihil import-results for formats, options, and the blocked-status mapping.2
Tier 2 — Run your suites through CruciHiL
Point The pytest plugin provides the async
crucihil run at your unmodified test tree with --framework:rig fixture; the Robot library exposes rig verbs as keywords. Results, reporters (--output, --html), and cloud sync are identical downstream regardless of who executed the tests. See crucihil run.3
Tier 3 — Mutation-verify your foreign suites
Prove your existing tests actually catch regressions — a strength report with zero rewrites:The simulated DUT is broken on purpose (dead DUT, stuck outputs, latency violations, declared faults) and every test is scored
caught, missed, or wrong_reason. See crucihil verify.The pytest plugin
When you run a pytest tree with--framework pytest, the CruciHiL pytest plugin:
- Injects the
rigfixture — an async fixture built from your rig TOML. Each test gets a fresh, connectedRig; it is disconnected after the test, so runs are isolated. - Maps outcomes onto CruciHiL statuses with the load-bearing distinction preserved:
Your test functions just take the fixture:
The Robot Framework library and listener
Robot suites use two pieces, both wired up automatically bycrucihil run --framework robot (the rig TOML path is passed as the ${RIG_TOML} variable):
CruciHiLLibrary exposes rig verbs as keywords. Robot keywords are synchronous; the library owns a background asyncio loop that hosts the rig, and every keyword bridges into it.
CruciHiLListener (Listener v3) streams Robot results as CruciHiL test results: PASS → pass, SKIP → skip, a FAIL whose message contains BlockedError → blocked, any other FAIL → fail.
The Blocked failure convention runs end-to-end: raise
BlockedError from a keyword (or use Block Test), and the result is blocked in the live listener, in the run summary, and even after a round-trip through output.xml and crucihil import-results.Drop --framework with a wrapper manifest
Wrap the foreign test tree once in a YAML manifest and run it like any native suite. The framework: field selects the executor; path: points at the foreign suite root:
framework: pytest or framework: robot requires path: — the manifest is validated at load time.
What stays the same
- Your test files. pytest tests and
.robotfiles run unchanged — no imports to rewrite, no annotations to add, no migration. - Your framework’s semantics. pytest collects and executes your tests; Robot runs your suites. CruciHiL wraps execution and translates results.
- Downstream behavior. JUnit XML / HTML reports, cloud sync, and mutation verification are identical whether a suite is native, pytest, or Robot.
rig fixture / keyword library for hardware access, the blocked≠fail distinction in your results, and CruciHiL’s history, dashboard, and verification on top of the test base you already have.
See also
crucihil import-results— Tier 1 command referencecrucihil run— run native or foreign suitescrucihil verify— mutation verification, including--framework- YAML Manifest Reference — the native suite schema