Assertions
Assertions verify that your machine behaves correctly. They're marked with the = prefix and appear in expect: blocks.
Basic Syntax
flow
expect:
= order is in #paid
= $total equals 1200
= @customer received :confirmationState Assertions
Current State
flow
expect:
= order is in #paid
= order is in #awaiting_payment
= application is in #pendingNot in State
flow
expect:
= order is not in #cancelled
= order is not in #failedState History
flow
expect:
= order has entered #processing
= order has been in #pending
= order has never been in #cancelledContext Assertions
Equality
flow
expect:
= $total equals 1200
= $status equals "active"
= $is_premium equals trueComparisons
flow
expect:
= $total is greater than 100
= $total is less than 2000
= $total is at least 100
= $total is at most 500
= $discount is between 10 and 50Not Equal
flow
expect:
= $status is not "cancelled"
= $retry_count is not 0Empty/Not Empty
flow
expect:
= $customer_name is not empty
= $errors is empty
= $items is not emptyCollection Assertions
Contains
flow
expect:
= $items contains "Laptop"
= $tags contains "urgent"
= $roles contains "admin"Count
flow
expect:
= $items has 3 items
= $items_count equals 3
= $errors has 0 itemsEmpty/Not Empty
flow
expect:
= $items is not empty
= $errors is empty
= $cart has itemsEvent Assertions
Event Received
flow
expect:
= @customer received :order_confirmed
= @payment received :refund_request
= @warehouse received :ship_orderEvent Emitted
flow
expect:
= :payment_request was emitted to @payment
= :notification was sent to @customerEvent Not Received
flow
expect:
= @customer did not receive :error
= :refund was not emittedEvent with Data
flow
expect:
= @payment received :payment_request with $total
= :order_confirmed was emitted with order_id: $order_idBoolean Assertions
flow
expect:
= $is_active is true
= $is_cancelled is false
= $has_discount is trueTimestamp Assertions
flow
expect:
= $created_at is not empty
= $updated_at is after $created_at
= $completed_at is todayNegation
Use not or is not for negative assertions:
flow
expect:
= order is not in #cancelled
= $total is not 0
= $items does not contain "Expired Item"
= @customer did not receive :errorMultiple Assertions
All assertions in an expect: block must pass:
flow
expect:
= order is in #paid // AND
= $total equals 1200 // AND
= @customer received :confirmation // AND
= $items has 3 items // All must passEvent-Level vs Scenario-Level
Event-Level (after specific event)
flow
on :checkout from @customer (api)
order moves to #awaiting_payment
expect:
= order is in #awaiting_payment // Checked after :checkoutScenario-Level (after all events)
flow
scenario: complete purchase
on :checkout from @customer (api)
...
on :payment_success from @payment
...
expect:
= order is in #paid // Checked after all eventsAssertion Patterns
Verify State Transition
flow
scenario: order payment
given:
order is in #pending
on :payment_received from @payment (api)
order moves to #paid
expect:
= order is not in #pending
= order is in #paidVerify Context Update
flow
scenario: apply discount
given:
$total: number is 100
$discount: number is 0
on :apply_coupon from @customer (api)
$discount becomes 10
$total decreases by $discount
expect:
= $discount equals 10
= $total equals 90Verify Event Communication
flow
scenario: order triggers payment
on :checkout from @customer (api)
emit :payment_request to @payment
expect:
= :payment_request was emitted to @payment
= @payment received :payment_requestVerify Error Handling
flow
scenario: handle invalid cart
given:
cart is empty
on :checkout from @customer (api)
? cart is empty
emit :checkout_error to @customer
expect:
= order is not in #processing
= @customer received :checkout_errorResponse Assertions
Verify API responses returned by reply statements.
Status Code
flow
expect:
= reply status is 201
= reply status is 400Field Values
flow
expect:
= reply.id is not empty
= reply.status equals "awaiting_payment"
= reply.total equals 1200Nested Fields
flow
expect:
= reply.customer.name equals "John"
= reply.customer.email is not empty
= reply.shipping.method equals "express"Field Presence
flow
expect:
= reply contains id
= reply contains customer
= reply does not contain tracking
= reply does not contain internal_idAsync Callback Assertions
Verify async callback delivery:
flow
expect:
= callback for :generate_report was sent
= callback for :process_order was not sentComplete Response Testing Example
flow
scenario: checkout flow
on :checkout from @customer (api)
$order_id becomes uuid()
order moves to #awaiting_payment
reply 201 with:
| id | $order_id |
| status | current_state |
| total | $total |
expect:
= order is in #awaiting_payment
= reply status is 201
= reply.id equals $order_id
= reply.status equals "awaiting_payment"
= reply contains total
= reply does not contain trackingSee Machine Responses for full response syntax.
Custom Assertions
For complex assertions, use natural language that maps to bindings:
flow
expect:
= payment was processed successfully
= inventory was updated correctly
= email was sent to customerThese map to custom assertion classes in your binding code.
Assertion Debugging
When assertions fail, you get detailed output:
✗ order is in #paid
Expected: #paid
Actual: #awaiting_payment
Event trace:
1. :checkout → #awaiting_payment
2. :payment_failed → #awaiting_payment (no transition)Best Practices
Be Specific
flow
// Good - specific
expect:
= $total equals 1200
= order is in #paid
// Avoid - vague
expect:
= order is valid
= everything workedTest What Matters
flow
// Good - testing the outcome
expect:
= order is in #paid
= @customer received :confirmation
// Avoid - testing implementation details
expect:
= internal_counter equals 5
= temp_flag is trueCover Edge Cases
flow
scenario: empty cart checkout
given:
cart is empty
on :checkout from @customer (api)
...
expect:
= order is not in #paid
= @customer received :empty_cart_errorGroup Related Assertions
flow
expect:
// State assertions
= order is in #completed
// Context assertions
= $total equals 1200
= $items_count equals 3
// Event assertions
= @customer received :confirmation
= @warehouse received :ship_orderValidation Assertions
Assertions for testing data validation and context constraints.
Validation Event Assertions
Verify that validation succeeded or failed:
flow
expect:
= :validation_failed was emitted
= :validation_failed was not emittedValidation Error Assertions
Check specific validation errors:
flow
expect:
= $errors contains "email"
= $errors contains "email.required"
= $errors contains "amount.greater than 0"
= validation error count is 2Constraint Violation Assertions
Verify context constraint behavior:
flow
expect:
= :constraint_violated was emitted
= :constraint_violated was not emitted
= $field was rolled back
= $retry_count is still 5Complete Validation Test Example
flow
scenario: checkout validation
on :checkout from @customer (api) with:
| field | value | validation |
| email | "not-an-email" | required, string, valid email |
| total | -50 | required, number, greater than 0 |
expect:
= :validation_failed was emitted
= order is not in #awaiting_payment
= validation error count is 2
= $errors contains "email"
= $errors contains "total"
scenario: context constraint check
given:
$retry_count: number is 5
on :retry_checkout from @customer (api)
$retry_count increases by 1
| $retry_count | required, integer, between 0 and 5 |
expect:
= :constraint_violated was emitted
= $retry_count is still 5Validation Assertion Patterns
| Assertion | Purpose |
|---|---|
= :validation_failed was emitted | Event validation failed |
= :validation_failed was not emitted | Event validation succeeded |
= :constraint_violated was emitted | Context constraint failed |
= $errors contains "field" | Specific field failed validation |
= validation error count is N | Exact number of errors |
= $field was rolled back | Context action was reversed |
= $field is still VALUE | Value unchanged after rollback |
See Data Validation for complete validation documentation.