VLearnVibium

How to Write Flake-Free Vibium Tests

Write flake-free Vibium tests by trusting auto-waiting, using semantic selectors, isolating state with browser contexts, and controlling the clock and network.

By Pramod Dutta··4 min read·Verified with Vibium 26.2
▶ Animated overview · made with Remotion

Flaky Vibium tests almost always come from brittle selectors and hardcoded sleeps — not from Vibium itself — and both are avoidable. Vibium auto-waits for every element to become actionable (visible, stable, receiving events, and enabled) before it acts, with a 30-second default timeout, so manual sleep() calls create races rather than preventing them. The recipe for stable tests is: target elements with semantic selectors (role, text, label, testid), delete arbitrary delays and trust auto-waiting, isolate state by giving each test a fresh browser context, and make time- or network-dependent behaviour deterministic with Vibium's built-in clock control and network mocking (both shipped in the 26.2 release). Do those four things and the overwhelming majority of intermittent failures disappear. This guide walks through each, with runnable Python examples using the verified browser_sync API.

What causes flaky tests in Vibium?

Flake is non-determinism: the same test passes and fails without code changes. The usual culprits are timing assumptions ("the button should be ready by now"), selectors that depend on volatile markup, and shared state leaking between tests (cookies, logged-in sessions, local storage). Vibium removes the timing class of flake automatically — but only if you let it, by not fighting auto-waiting with your own sleeps.

How do I rely on auto-waiting instead of sleeps?

Delete fixed delays and let Vibium poll for actionability. A sleep(2) either wastes time when the page is fast or fails when it is slow — it can never be right. Vibium instead waits for the element to actually be ready.

from vibium import browser_sync as browser
 
vibe = browser.launch()
vibe.go("https://app.example.com/dashboard")
 
# Anti-pattern: guessing how long to wait
# time.sleep(3)
# vibe.find("#save").click()
 
# Better: Vibium waits until #save is actionable (up to 30s)
vibe.find("#save").click()
 
vibe.quit()

If a specific element legitimately takes longer (a heavy report, say), raise the timeout for that one action rather than sprinkling global sleeps:

vibe.find(role="button", text="Generate report").click(timeout=60000)

To understand exactly what "actionable" means, read how actionability works.

Which selectors keep tests stable?

Use semantic, intent-based selectors so a UI refresh does not break your suite. Selecting by role and text or by testid ties the test to what the element is, not where it sits in the DOM.

# Stable: survives CSS refactors and reordering
vibe.find(testid="checkout").click()
vibe.find(role="button", text="Place order").click()
vibe.find(label="Coupon code").type("SAVE10")
 
# Fragile: breaks when classes or positions change
# vibe.find("div.cart > button:nth-child(4)").click()

This is the single highest-leverage change for stability. The companion guide selector best practices covers the full priority order.

How do I isolate state between tests?

Give each test its own browser context so cookies, storage, and sessions never leak. A test that "passes only when run after the login test" is hidden flake. In Vibium 26.2, browser contexts are isolated sandboxes — create one per test and set up exactly the cookies you need.

# Conceptual per-test isolation using a fresh context
ctx = bro.new_context()
vibe = ctx.page()
 
# Seed only the state this test needs
ctx.set_cookies([
    {"name": "session", "value": "test-token", "url": "https://app.example.com"}
])
 
vibe.go("https://app.example.com/account")
# ... assertions ...
 
ctx.clear_cookies()

Seeding auth via cookies also skips slow, flake-prone UI logins. For the end-to-end version, see automate login with Vibium.

How do I make time and network deterministic?

Control the clock and mock the network so external variability can't fail your test. Tests that depend on real time (countdowns, "expires in 5 minutes", date formatting) or real APIs (latency, flaky staging) are inherently non-deterministic. Vibium 26.2 lets you freeze time and intercept requests.

# Freeze browser time so timer-based UI is deterministic
vibe.clock.install()
vibe.clock.set_fixed_time("2026-06-15T09:30:00")
vibe.clock.fast_forward(30000)  # advance 30s on demand
 
# Mock an API so the test never depends on a live backend
vibe.route("**/api/orders", lambda route: route.fulfill(
    status=200,
    body='[{"id": 1, "status": "shipped"}]'
))

Mocking the backend removes an entire category of "the staging server was slow" failures. For observing real traffic instead of mocking it, see monitor network requests.

The flake-free checklist

  • Trust auto-waiting; remove every arbitrary sleep().
  • Select by role, text, label, or testid — never by position.
  • One fresh browser context per test; seed state explicitly.
  • Freeze time with clock control for timer-dependent UI.
  • Mock unstable APIs with network routing.
  • When one action is genuinely slow, raise its timeout — don't slow the whole suite.

Stable tests are mostly a discipline of removing assumptions. Lean on Vibium's actionability engine, isolate state, and pin down time and network. From here, explore test a SPA and the wait for element command.

Frequently asked questions

Why are my Vibium tests flaky?

Most flake comes from brittle selectors and fixed sleeps, not Vibium itself. Vibium auto-waits for elements to become actionable, so hardcoded delays cause races. Use semantic selectors, remove arbitrary sleeps, and isolate state per test with fresh browser contexts to eliminate most flakiness.

Does Vibium have automatic waiting?

Yes. Before every click, type, or fill, Vibium polls until the element is visible, stable, receiving events, and enabled — its actionability checks. The default timeout is 30 seconds and is configurable per action, so you rarely need explicit waits.

How do I make time-dependent Vibium tests deterministic?

Use Vibium's clock control to freeze or fast-forward browser time. Install the clock, set a fixed time, then advance it on demand. This makes tests that depend on timers, dates, or countdowns deterministic instead of depending on real wall-clock timing.

Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.

Related guides