How to Do Visual Regression Testing with Vibium
Do visual regression testing with Vibium in Python — capture PNG baselines with screenshot(), diff them on every run, and catch unintended UI changes.
To do visual regression testing with Vibium, capture a baseline PNG with screenshot(full_page=True), save those bytes, then on every later run capture again and diff the two images — if they differ beyond a threshold, the UI changed. Vibium's screenshot() returns raw PNG bytes rather than a file path, which makes it trivial to pipe an image into a diff library like Pillow or a hosted visual-testing service without touching disk. Because Vibium auto-waits for the page load before capturing, your baselines are complete rather than half-rendered. The core loop is simple: render the page, screenshot it, and compare against a known-good image. Visual regression catches the bugs assertions miss — a broken layout, a clipped button, a font that failed to load — all of which still pass a text() check but look wrong to a human.
What is the visual regression script?
from vibium import browser_sync as browser
vibe = browser.launch()
vibe.go("https://example.com")
png = vibe.screenshot(full_page=True)
with open("baseline.png", "wb") as f:
f.write(png)
vibe.quit()Run this once to record a baseline. It opens the page, captures the full scrolling document as PNG bytes, and writes them to baseline.png. That file becomes the reference every future run compares against.
How does each step work?
browser.launch()— starts Chrome over WebDriver BiDi; no driver download needed.vibe.go(url)— navigates and waits for the load event so the capture is complete.vibe.screenshot(full_page=True)— captures the entire scrolling page (not just the viewport) as PNG bytes. See the screenshot command reference for every option.open(...).write(png)— you decide where the bytes land: a baseline file, an upload, or an in-memory buffer.vibe.quit()— closes the browser and cleans up.
The key idea is that screenshot() hands you bytes, so the image flows straight into whatever diff tool you choose.
How do I compare a new run against the baseline?
Capture the current page, then diff it against the saved baseline with Pillow. If the difference exceeds your threshold, fail the test and write a diff image so a human can review what moved:
from vibium import browser_sync as browser
from PIL import Image, ImageChops
import io
vibe = browser.launch()
vibe.go("https://example.com")
current = Image.open(io.BytesIO(vibe.screenshot(full_page=True)))
vibe.quit()
baseline = Image.open("baseline.png")
diff = ImageChops.difference(baseline.convert("RGB"), current.convert("RGB"))
bbox = diff.getbbox()
if bbox is not None:
diff.save("diff.png")
raise AssertionError(f"Visual change detected in region {bbox} — see diff.png")
print("No visual change.")ImageChops.difference() returns a per-pixel delta; getbbox() is None when the images match exactly. For real sites, allow a small tolerance rather than demanding a pixel-perfect match.
How do I make visual tests stable?
The number-one cause of flaky visual tests is content that legitimately changes between runs. Pin the viewport so layout is deterministic, and wait for a late-loading element before you capture so nothing is mid-render:
vibe = browser.launch(window_size=(1280, 800))
vibe.go("https://example.com/long-page")
# Wait for a late element so the page is fully rendered before capture
vibe.find("footer").text()
png = vibe.screenshot(full_page=True)Other stabilizers worth adding:
- Mask dynamic regions — overlay or crop out timestamps, ads, and carousels that change every load.
- Wait for fonts and images — a flash of unstyled text produces false diffs; wait for a known element that depends on them.
- Use element screenshots — call
screenshot()on a singlefind()result to test one component in isolation, reducing noise from unrelated changes.
How do I capture just one component?
Find the element first, then screenshot only that region. Component-level baselines produce far fewer false positives than full-page diffs because unrelated parts of the page cannot trip them:
card = vibe.find(".pricing-card")
png = card.screenshot()
with open("pricing-card.png", "wb") as f:
f.write(png)Why Vibium for visual regression?
Vibium gives you PNG bytes directly, real-Chrome rendering, and auto-wait on page load — the three things a visual pipeline needs. Compared with heavier frameworks, there is no driver to manage and the API is tiny, so wiring it into CI is mostly your diff logic, not setup. If you are weighing options, see Vibium vs Playwright for an honest comparison of the trade-offs.
Next steps
Frequently asked questions
How do I do visual regression testing with Vibium?
Capture a baseline image with screenshot(full_page=True), save the PNG bytes, and on later runs capture again and compare the two with an image-diff library like Pillow. If the pixels differ beyond a threshold, the UI changed and the test fails so you can review it.
What format does Vibium return screenshots in?
Vibium's screenshot() returns raw PNG bytes, not a file path. You can write them to disk as a baseline, feed them straight into a diff library, or push them to a visual-testing service — all without an intermediate file, which keeps the comparison pipeline simple.
How do I make visual tests stable across runs?
Pin the viewport size, wait for fonts and images to finish loading, and mask dynamic regions like dates or ads before capturing. Vibium auto-waits for the page load, so the main source of flakiness is animated or time-varying content, which you hide or stabilize.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
How to Automate a Checkout Flow with Vibium
Automate an e-commerce checkout with Vibium in Python — add to cart, fill shipping and payment fields, place the order, and verify the confirmation page.
4 min read→How-To RecipesHow to Automate a Google Search with Vibium
Automate a Google search with Vibium in Python — open Google, type a query, submit it, and read the result titles in about ten lines of code.
3 min read→How-To RecipesHow to Automate a Multi-Tab Flow with Vibium
Automate a multi-tab flow with Vibium in Python — open new tabs with new_page(), switch with bring_to_front(), capture popups, and close tabs cleanly.
3 min read→How-To RecipesHow to Automate a Search Box with Vibium
Automate a search box with Vibium in Python — find the input, type your query, press Enter, wait for results to render, and read them back with findAll.
3 min read→