RclexTesting.DSL.Events (RclexTesting (Experimental) v0.12.3)

Copy Markdown View Source

Assert event order and workflow behavior across ROS topics, services, and actions.

Build event descriptors with message/1, service_call/1, goal/1, feedback/1, and result/1. Pass them to expect_sequence/1, expect_before/2, expect_after/2, expect_together/1, or expect_workflow/1 to query the scenario's unified event log.

Summary

Functions

Assert that event described by later_spec occurred after earlier_spec.

Assert that event described by first_spec occurred before second_spec.

Assert that a sequence of events happens in arrival order across any mix of topics, services, and actions.

Assert that all given event descriptors are eventually satisfied in any order.

Assert a cause-and-effect workflow described as a keyword list.

Descriptor for feedback published by action action_name.

Descriptor for a goal submitted to action action_name.

Descriptor for a message arriving on topic.

Descriptor for a result produced by action action_name.

Descriptor for a service call received on service_name.

Functions

expect_after(later, earlier, opts \\ [])

Assert that event described by later_spec occurred after earlier_spec.

Inverse of expect_before/2 — a readability alias. Returns {earlier_payload, later_payload}.

expect_after(
  message("/robot/state", matches(%{mode: :completed})),
  message("/robot/state", matches(%{mode: :running}))
)

expect_before(first, second, opts \\ [])

Assert that event described by first_spec occurred before second_spec.

Both events are awaited in order; this guarantees first was logged before second. Returns {first_payload, second_payload}.

expect_before(
  service_call("/safety/check"),
  message("/robot/state", matches(%{mode: :running}))
)

expect_sequence(specs)

@spec expect_sequence([RclexTesting.DSL.Events.EventSpec.t()]) :: [struct()]

Assert that a sequence of events happens in arrival order across any mix of topics, services, and actions.

Each element is an event descriptor from message/1,2, service_call/1,2, goal/1,2, feedback/1,2, or result/1,2. Every event must arrive strictly after the previous one (based on the global event log).

Returns the list of matched payloads in sequence order.

watch "/mission/start", MissionStart
watch "/robot/state", RobotState
mock_service "/safety/check", SafetyCheck, fn _ -> %SafetyCheck.Response{allowed: true} end
mock_action "/navigate", Navigate, fn _goal, _fb -> %Navigate.Result{success: true} end

expect_sequence [
  message("/mission/start"),
  service_call("/safety/check"),
  goal("/navigate"),
  result("/navigate", fn r -> r.success end),
  message("/robot/state", matches(%{mode: :completed}))
]

expect_together(specs, opts \\ [])

@spec expect_together(
  [RclexTesting.DSL.Events.EventSpec.t()],
  keyword()
) :: [struct()]

Assert that all given event descriptors are eventually satisfied in any order.

Passes as soon as every condition has been observed (at least once). Each event in the log can satisfy at most one descriptor (greedy left-to-right matching). Returns the list of matched payloads in descriptor order.

expect_together [
  message("/robot/state", matches(%{mode: :running})),
  message("/battery/state", matches(%{charging: false}))
]

expect_workflow(steps, opts \\ [])

@spec expect_workflow(keyword(), keyword()) :: [struct()]

Assert a cause-and-effect workflow described as a keyword list.

:given defines the trigger event; each :then defines a subsequent step. Internally compiled to expect_sequence/1. Returns all matched payloads.

expect_workflow [
  given: message("/mission/start"),
  then:  message("/robot/state", matches(%{mode: :running})),
  then:  message("/robot/state", matches(%{mode: :completed}))
]

feedback(action_name, predicate \\ fn _ -> true end)

@spec feedback(String.t(), (struct() -> boolean())) ::
  RclexTesting.DSL.Events.EventSpec.t()

Descriptor for feedback published by action action_name.

feedback("/navigate")
feedback("/navigate", fn fb -> fb.progress >= 50 end)

goal(action_name, predicate \\ fn _ -> true end)

Descriptor for a goal submitted to action action_name.

The action must already be mocked via mock_action/3.

goal("/navigate")
goal("/navigate", fn g -> g.x > 0 end)

message(topic, predicate \\ fn _ -> true end)

Descriptor for a message arriving on topic.

Use as a building block for expect_sequence/1, expect_before/2, etc. The topic must already be watched via watch/2 (or expect/3) before the sequence assertion runs.

message("/mission/start")
message("/robot/state", &(&1.mode == :running))
message("/robot/state", matches(%{mode: :running}))

result(action_name, predicate \\ fn _ -> true end)

Descriptor for a result produced by action action_name.

result("/navigate")
result("/navigate", fn r -> r.success end)

service_call(service_name, predicate \\ fn _ -> true end)

@spec service_call(String.t(), (struct() -> boolean())) ::
  RclexTesting.DSL.Events.EventSpec.t()

Descriptor for a service call received on service_name.

The service must already be mocked via mock_service/3.

service_call("/safety/check")
service_call("/safety/check", fn req -> req.robot_id == "r1" end)