Octov0.11.7
Guides

Testing

Unit-test octo flows with dolphin: mock what calls the world, assert what happened, and run the same file from a terminal, the editor, an agent and CI.

dolphin is octo's test runner. A test is a debug config with assertions: the input, mocks and spies you would pass to octo invoke by hand, plus what should have happened. The mocks make the flow runnable anywhere (the HTTP call, the LLM, the database write never happen); the assertions make the run mean something.

The editor's Testing tab: a rail of flows, one with a suite of two cases and one with none yet

One file, four surfaces

A suite is a YAML file beside the flows it tests: orders.yaml is tested by orders_test.yaml.

You write itYou run it
By hand, in an editordolphin test in a terminal
In the Testing tab, as a formRun tests, per suite or for the whole document
With an agent over MCPrun_tests
(any of the above)CI, on every push

All four give the same verdict because all four shell out to the same binary. The editor runs dolphin and reads its report.

The shape of a suite

orders_test.yaml
flow: orders                       # the flow every case calls

mocks:                             # stand in for the blocks that call the world
  orders.charge-card:
    cases:
      - when: 'body.amount > 100'
        error: card declined
    default:
      body: { id: ch_1, status: captured }

inputs:                            # named messages the cases share
  small: { data: { amount: 10 } }
  large: { data: { amount: 500 } }

cases:
  - name: a small charge is captured
    input: small
    expect:
      body: { id: ch_1, status: captured }

  - name: a large charge is declined and answers 502
    input: large
    expect:
      vars: { httpStatus: 502 }
      that: ['body.error.contains("card declined")']
    spies:                         # and prove the block was actually reached
      orders.charge-card:
        count: 1

Start here

What dolphin is not

It is not an assertion DSL: expect.that and a mock's when are CEL, the same language every block uses, over the same variables.

It is not an in-process harness: one case is one octo process, so cases are fully isolated and a failing case can hand you a runnable command that reproduces it.

It is not a mock of octo: the engine under test is the real one, so a mocked block failure behaves exactly as the real failure would in production.

dolphin ships alongside octo as a second binary. See installation, or use the standalone editor's Docker image, which bundles both.

On this page