Smarter Test Automation with CaGe in miniHIL
A domain-specific language for defining, composing, and automatically generating ECU test cases — from basic functional checks to comprehensive state-transition coverage.
Writing test cases manually for complex embedded systems is slow, error-prone, and doesn't scale. CaGe — the Case Generator language built into miniHIL — is designed to solve exactly that.
CaGe is a domain-specific language developed by PROTOS Software for modelling test logic inside miniHIL. It integrates directly with eTrice, shares the same actor-based runtime as the simulation layer, and outputs xUnit-compatible XML — a natural fit for CI/CD pipelines.
The Core Building Blocks
- Step (Foundational): The leaf node of every test. A Step defines one or more pairs of action and reaction — stimulating the SUT and asserting its response. Steps cannot call other Steps.
- Sequence (Composable): Composes Steps and other Sequences into reusable test procedures. Like a function call in C or Java — parameterised, nestable, and independently executable.
- TestSuite (Structure): The root container for test cases. Direct children of a TestSuite are treated as independent test cases — if one fails, the next continues. Results map to xUnit XML.
- TestCase (Structure): An alias for Sequence at the top level of a TestSuite. Semantically identical, but signals intent clearly: this is a named, independent unit of validation.
Step setOn: // protect test from running forever timeout 100 ms action motor.start() reaction expect motor.running == true ; TestSuite MotorTests: setOn // called as a test case ;
Action and Reaction — Stimulate and Observe
Every Step is built from action and reaction blocks. Actions send stimuli to the SUT. Reactions define expected responses using two temporal operators: expect next (matches the immediately next message — fails if data doesn't match) and expect finally (waits for a matching message, ignoring intermediate ones — useful for periodic or asynchronous signals).
State Transition Testing — Exhaustive Coverage, Automatically
For complex ECU behaviours with many states, manually writing every test case is impractical. CaGe's StateTransitionGraph eliminates this by generating test cases automatically from a graph model. Engineers define states and transitions, annotating each with the Steps that implement the test logic. CaGe derives test paths and generates a complete TestSuite automatically.
StateTransitionGraph ATM: State InsertCard: => EnterPin [ insertCard ] ; State EnterPin: => WithdrawMoney [ inputCorrectPin ] => EnterPin2 [ inputBadPin ] => ReleaseCard [ exit ] ; State WithdrawMoney: => ReleaseCard [ checkMoney ] ; State End ; ; TestSuite ATMTestSuite: generate ATM n-switch = 0 ;
The n-switch argument controls coverage depth: n-switch 0 visits each transition at least once; n-switch 1 covers all consecutive transition pairs; n-switch 2 is appropriate for safety-critical certification requirements.
Advanced Features
- Parameterised Sequences and Graphs: Steps and Sequences accept typed parameters, enabling combinatorial test variants from a single definition.
- Runtime test recording with PlantUML: CaGe records actions and reactions at runtime and renders them as PlantUML sequence diagrams — invaluable for debugging failures without re-running the system.
- Deep C/C++ integration: Target code can be embedded directly inside Steps and Sequences using backtick syntax. Includes, defines, and complex data comparisons in native C integrate seamlessly with CaGe logic.
The miniHIL + eTrice + CaGe Stack
CaGe is the test authoring layer of a cohesive three-tier stack: miniHIL provides the hardware interface, eTrice provides the environment modeling framework, and CaGe provides the test language that drives validation. All three share the same runtime — no protocol translation, no timing gaps. For ECU validation teams, this means a single, consistent toolchain from simulation model to CI report, running on a workbench unit every developer can own.