Drop messages, delay topics, kill nodes, and corrupt payloads under a context manager. Test E-stops, comms loss, and sensor failures the way an auditor expects.
Functional tests prove the robot works. Fault tests prove it fails safely. Both are required by every safety standard you’ll certify against (ISO 13849, IEC 61508, EU MR 2023/1230 Annex III). Roboticks ships four fault-injection primitives that operate over the rclpy DDS layer without modifying the system under test.
Fault injection runs between rclpy and the node — it manipulates the DDS layer for the test process. It does not require root, does not need a custom DDS vendor, and does not patch your node.
All four are context managers. The fault is scoped to the with block. On exit, the original behaviour is restored, even if the test asserts inside the block.
from roboticks.fault_injection import ( drop_messages, delay_messages, kill_node, corrupt_topic,)
Rule of thumb: mock until the node is built; inject once it’s running. Roboticks’s evidence pack tags fault-injection tests separately so the auditor sees them without you having to label by hand.
The safety requirement is “E-stop functions even if the supervisor’s heartbeat is lost.” A passing test asserts the robot enters a safe stop state when /supervisor/heartbeat stops arriving.
from roboticks import confirmsfrom roboticks.fault_injection import kill_nodefrom roboticks.assertions import assert_topic_publishedfrom lifecycle_msgs.msg import TransitionEvent@confirms("REQ-098")def test_planner_respawned_by_watchdog(ros_context): with kill_node("nav2_planner"): # Watchdog should observe the death and republish a transition evt = assert_topic_published( "/nav2_planner/transition_event", TransitionEvent, within=5.0, predicate=lambda m: m.transition.label == "configure", ) assert evt is not None
Fault-injection tests get a dedicated section in the evidence pack PDF: requirement → fault primitive → topic → result. Auditors quote that section verbatim when defending the safety case.