Skip to content
Jose Constela
Go back

Ronsel: Tests You Read, Docs You Run

Today I’m launching ronsel.

If the idea feels familiar, it should: ronsel is the new name for the tool I wrote about as lab34-flows. Same problem, a much better answer to it. The name changed because the tool did.

The ronsel landing page: "Tests you read. Docs you run."

Why rename it

The original pitch was “declarative E2E testing with YAML.” That was right about the disease and only half right about the cure.

Moving test logic out of code and into YAML did fix the fragility. What it didn’t fix was the reading problem. A YAML file tells you what runs. It doesn’t tell you why this scenario matters, what the business rule is, or what someone should conclude when step three fails. That knowledge stayed where it always was — in one engineer’s head, or in a Jira ticket nobody executes.

So the format changed. A flow is now a Markdown document: prose explaining the scenario, with executable step blocks in the middle of it. You read it top to bottom like a document, and you press Run.

Hence the tagline: tests you read, docs you run.

ronsel is the wake a boat leaves behind it in Galician — the visible trail that proves something passed through. That’s what these documents are.

The three problems it’s aimed at

The site states them plainly, and they’re the three I kept hitting:

  1. Knowledge silos. Complex test logic locked inside one engineer’s code becomes unmaintainable the moment that engineer moves on.
  2. Test cases that never run. QA writes careful scenarios in Jira. The pipeline never executes a single one of them.
  3. Fragmented coverage. Real workflows cross APIs, databases, brokers and browsers. Testing tools insist on looking at one component at a time.

One document, three systems, one answer

Here’s the example flow from the site. A delivery fails and the parcel has to be rescheduled — which means the tracking API, the warehouse database and the picking screens all have to agree about what just happened.

A ronsel flow document: frontmatter, prose, and an executable step block

Look at what’s in that one file:

The step above also shows two things worth calling out. {{ randomName }} and {{ randomInt0_9999 }} are replacers, so every run uses fresh data. And mimic swaps out the courier’s label service for a local stand-in, which is why this flow runs identically on a laptop with no VPN and in staging.

Assertions go beyond equality when they need to:

test:
  status: 201
  body:
    status: "in_transit"
    trackingRef: "$expr: typeof value === 'string' && value.length > 0"

And the asynchronous part — the bit that’s genuinely hard to test — is a first-class step, not a sleep:

test:
  status: 202
  latentApplications:
    - application: mqtt
      client: warehouse
      test:
        - topic: "wms/shipments/{{ shipmentId }}"
          message:
            status: "reattempt_scheduled"
      retry:
        attempts: 3
        delay: 2

The MQTT client subscribes before the flow starts, so nothing is missed while the HTTP call is in flight.

Evidence lives under the step

When a flow runs, the request, the response, the timing and the assertion result appear inline, directly beneath the step that produced them. No console log to scroll, no report to cross-reference.

A flow running in the app, with request, response body and assertion results under the step

This is the part that changes who can use it. A product manager can open a flow, read the prose, run it, and see HTTP 200, the actual response body, and “All assertions passed” without asking anyone what any of it means.

Folders are tables

Because every flow carries structured frontmatter, a folder of flows renders as a sortable table — every property a column.

A folder of flows rendered as a sortable table with owner, priority, tags, review state and coverage columns

You get computed columns for properties you derive rather than store:

if(flow.steps > 3, "deep", "shallow")

And saved views — “Release readiness”, “Critical” — live in a views.yaml kept in git alongside the flows, so the way your team looks at coverage is versioned like everything else.

AI writes the first draft

There are two AI entry points, and both of them are careful about the same thing: you read the result before it counts.

The AI flow generator: describe a scenario in plain words and get a flow built against your applications

Describe a scenario in plain words — “a parcel is reported lost in transit, open a claim, put the shipment on hold, verify the customer gets a refund” — and you get a flow written against your registered applications and methods, not a generic template. There’s also an edit mode that rewrites an existing flow from an instruction, and the result stays unsaved until you’ve read it.

Providers are Ollama, Gemini or Claude. Point it at a local Ollama and the whole feature runs on your machine.

What it can talk to

Nothing leaves the house

Ronsel is local-first, and that isn’t a marketing line — it’s the deployment model:

Getting started

mkdir e2e && cd e2e
npx ronsel start
# → http://localhost:3001

After that first run:

npm run ronsel

And in CI, the same file, headless, with one flag to switch environment:

ronsel --file flows/logistics/failed-delivery-retry.md --env staging
wms · createShipment          ✓ passed   212 ms
warehouse-db · query          ✓ passed     8 ms
wms · reportDeliveryAttempt   ✓ passed   2.3 s · mqtt attempt 2/3
warehouse-db · query          ✓ passed     6 ms

4 steps, 0 failures
$ echo $?
→ 0

The document your product manager read this morning is the thing that just gated the deploy. That’s the whole point.

What it isn’t

Worth saying out loud: ronsel is not a unit testing framework, not a load testing tool, and not a production-ready browser automation suite — the Playwright integration is experimental and marked that way on purpose.

Free, MIT, and yours

No per-seat licensing, no paid tier, no account to install it. Free. Full stop.

Working tools are better proof than slides. Ronsel is the tool I wanted the day a bug lived between three systems and nobody on the team could read the test that should have caught it.

Try it, break it, and tell me what’s missing.


Share this post on:

Next Post
Introducing lab34-flows: Declarative E2E Testing with YAML