The expensive part of end-to-end testing isn’t the test — it’s getting to the point where the test can run. You sign in, navigate four pages deep, seed some data, and then you’re ready to exercise one assertion. Do that serially for every scenario and your suite spends its life re-setting-up. Vers lets you set up once, branch at the decision point, and run every scenario in parallel against its own live copy of that state.Documentation Index
Fetch the complete documentation index at: https://docs.vers.sh/llms.txt
Use this file to discover all available pages before exploring further.
What you’ll build
- A small Flask shopping-cart app running inside a Vers VM
- A “pre-checkout” state with a user signed in and items in the cart
- Three branches exercising different checkout scenarios (valid card / expired card / empty cart edge case) — all in parallel, against live isolated state
- Time: ~20 minutes
Prerequisites
- Vers CLI installed and authenticated
- Basic familiarity with HTTP and the command line
The idea
Traditionally, each test re-creates its setup. Scenario A does login → browse → add-to-cart → test A. Scenario B does login → browse → add-to-cart → test B. The shared prefix gets paid over and over. With Vers you do login → browse → add-to-cart once, branch the running VM at that exact moment (memory, sockets, in-flight session — all of it), then run scenario A on one branch, scenario B on another, scenario C on a third. Every branch is live and independent. The setup prefix is paid once and inherited for free.Step 1: Initialize the project
vers.toml — the Flask app is tiny, so default resources are fine:
Step 2: Boot the VM and install the app
/app/server.py) — two endpoints, in-memory state:
{"ok":true,"user":null}.
Step 3: Navigate to the pre-checkout state
Still inside the VM, drive the app into a meaningful state — a signed-in user with two items in the cart:["book", "mug"], server process is running and holding that state in memory.
Exit back to your host shell:
Step 4: Branch the live state
Branch the running VM. Each child inherits the Flask process, the in-memory cart, and alice’s session — live.branch call each.
Step 5: Run divergent scenarios in parallel
Scenario A — happy path (valid card)
{"ok": true, "total": 20.0, "items": ["book", "mug"]}
Scenario B — expired card
{"ok": false, "error": "card_expired"}
Scenario C — double checkout edge case
This one exercises a more interesting property of branching: the scenario mutates state and asserts a second call fails cleanly.True parallelism across terminals
For visible parallelism, open three terminals and run the three scenarios simultaneously. They’ll finish in roughly the time of the slowest single scenario — not the sum.Step 6: Verify isolation
Re-run scenario A after scenario C has mutated state in its branch. It still succeeds because each branch has its own memory:{"ok": true, ...}. This is the key property: branches aren’t shared mutable state. They’re siblings.
Step 7: Clean up
-r tears down the root and all descendants.
The pattern
Set up expensive state once, branch at the decision point, run every scenario in parallel. This works anywhere the setup cost is asymmetric with the test cost:- End-to-end tests that require login + navigation + seeding
- Database migrations where you want to try three approaches against a populated dataset
- Fuzzing — branch a running server, throw divergent inputs at each branch
- Reproducing stateful bugs — branch at the suspicious moment, explore from there without losing the setup
What’s next
Database state testing
Same pattern, applied to testing parallel schema migrations against a seeded database.
Agent swarms
Branch the same golden state into N parallel agents.
vers branch
Every flag on the branch primitive.
Architecture
How branches inherit live memory without paying for a full copy.