Examples
Four end-to-end examples. Each one is self-contained, traces back to a requirement, and exercises a different SDK capability.| Example | Capability shown |
|---|---|
| 1. E-stop deadline test | @confirms, @deadline, rclpy assertion helpers |
| 2. Navigation drift test | @requires_sim, assert_tf_transform, MCAP capture |
| 3. Sensor-loss fault injection | fault_injection.drop_messages, mixed assertions |
| 4. Multi-node launch test | launch_testing, post-shutdown assertions |
1. E-stop deadline test
Requirement —REQ-001: E-stop halts motion within 100 ms.
This is the minimal interesting test. One decorator, one deadline, one rclpy helper.
REQ-001 → tests.test_estop::test_estop_halts_motion_within_100ms → passed.
2. Navigation drift test
Requirement —REQ-031: Robot reaches the goal pose within 0.5 m of target after 30 s in the warehouse_loop world.
This test needs a 3D physics world (Gazebo) and ends with a TF assertion. We record an MCAP for failure forensics.
hosted-gazebo-gpu pool because of @requires_sim("gazebo", gpu=True). If you have a self-hosted GPU runner labelled gpu=true, it runs there for free instead.
3. Sensor-loss fault injection
Requirements —REQ-061: Robot decelerates gracefully on LIDAR loss. REQ-062: Robot publishes a warning on LIDAR degradation.
This test confirms two requirements with one scenario. We drop 80% of /scan messages and assert that the robot slows (not stops, not crashes) and emits a warning.
@confirms("REQ-061", "REQ-062") lights up both rows of the matrix from the same test.
4. Multi-node launch test
Requirement —REQ-098: When nav2_planner is killed, the watchdog restarts it within 5 s and re-emits a "configure" transition event.
This needs the planner running as a real separate process, plus a watchdog, plus an observer. Launch testing is the right tool.
Patterns common to all four
- Session-scoped
rclpy.init()/rclpy.shutdown(). Put it inconftest.pyonce. - One
@confirms(...)per intentional traceability link. Avoid spraying requirement IDs across unrelated tests. - MCAP capture only when the failure forensics matter. It’s cheap, but not free; default to
upload_on="failure". - Sim only when sim is the only way. A test that needs Gazebo is a test that needs a GPU and a sim minute — pay for it deliberately.
Where to copy from
Theroboticks-sdk repo has these examples (and more) as runnable code:
Next
Decorators
The decorators these examples lean on.
Assertions
The rclpy helpers the examples invoke.
Fault injection
The primitives example 3 uses.
Launch testing
The system-test pattern example 4 follows.