Vibium with Allure Reports
Wire Vibium into Allure Reports — attach screenshots, steps, and page HTML to a rich HTML report from your pytest, Jest, or Cucumber Vibium suite.
To use Vibium with Allure Reports, keep Vibium as your browser layer and bolt Allure on as a reporter for whatever test runner you already use — pytest, Jest, or Cucumber — then attach Vibium's screenshots, page HTML, and steps as evidence. Vibium is AI-native browser automation built on WebDriver BiDi, shipped as a single Go binary that auto-downloads Chrome, created by Selenium and Appium co-creator Jason Huggins. It deliberately ships no reporter of its own, which is exactly why Allure slots in so cleanly: Allure hooks into your runner, not into Vibium. You install the runner's Allure adapter (allure-pytest for Python, an Allure adapter for Jest or Cucumber in JS), drive the browser with Vibium's normal find() / click() / screenshot() API, and in a teardown hook you pass the PNG bytes from screenshot() straight into an Allure attachment. Run the suite, point allure serve at the results folder, and you get a polished HTML report with failure screenshots, collapsible steps, history trends, and severity — turning a green-or-red console run into a shareable, debuggable artifact.
How does Vibium fit into an Allure report?
Vibium and Allure occupy two different layers that never overlap. Vibium is the automation engine — it launches Chrome over WebDriver BiDi, finds elements, clicks, types, and reads state. Allure is the reporting engine — it collects the pass/fail outcome of each test plus any attachments and renders them as a rich, interactive HTML site. Between them sits your test runner (pytest, Jest, Cucumber), which owns the test lifecycle and is where Allure actually hooks in.
That separation is the whole reason the pairing is painless. You do not need a "Vibium reporter" because Allure never talks to Vibium directly. Your runner runs a test, the test uses Vibium to do browser things, and at the end the runner tells Allure whether the test passed and hands over whatever evidence you attached. Vibium's contribution to the report is data: screenshot bytes, page HTML, console logs, and the names of the steps you wrapped.
If Vibium itself is new to you, start with what is Vibium and install Vibium, then come back here to add reporting on top.
What does the Vibium-to-Allure pipeline look like?
Every Vibium-plus-Allure run follows the same five stages, regardless of language. First, your runner executes a test that drives the browser with Vibium. Second, the test (or a hook) captures evidence — a screenshot(), the page's HTML, console logs. Third, the Allure adapter writes a JSON result file plus attachment files into an allure-results directory. Fourth, the Allure CLI reads that folder and builds a static HTML report. Fifth, you open or publish that report.
The important nuance is when evidence is captured. The strongest signal in any browser report is a screenshot of the page at the exact moment a test failed, so you attach it from a teardown hook that only fires on failure. That single practice — screenshot-on-failure wired into the report — is what makes an Allure report genuinely useful for a browser suite rather than just a prettier pass/fail list.
| Layer | Owns | Tool |
|---|---|---|
| Automation | Launch Chrome, find, click, type, screenshot | Vibium (Go binary + BiDi) |
| Orchestration | Test lifecycle, hooks, pass/fail | pytest, Jest, or Cucumber |
| Reporting | Aggregate results, attachments, history, HTML | Allure + runner adapter |
How do I set up Allure with Vibium and pytest?
For Python, install allure-pytest alongside Vibium and pytest, then let the adapter emit result files as your tests run. Vibium is free (pip install vibium) and bundles its BiDi engine into one binary, so there is nothing to version-match; allure-pytest is the only new dependency the report needs.
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install vibium pytest allure-pytest
vibium install # pre-download Chrome for Testing (optional)You also need the Allure command-line tool to view results — it is a separate binary (install via brew install allure, scoop install allure, or the Allure release archive). Run your suite so the adapter writes results, then serve them:
pytest --alluredir=allure-results
allure serve allure-results # builds + opens the HTML report--alluredir tells the adapter where to drop the raw JSON and attachment files; allure serve turns that folder into a live report in your browser. Nothing here is Vibium-specific yet — the next step is feeding Vibium's evidence into those results.
How do I attach a Vibium screenshot on failure?
Wire a teardown fixture that grabs a Vibium screenshot when a test fails and hands the bytes to allure.attach(). Vibium's screenshot() returns raw PNG bytes, and Allure's attachment API accepts bytes directly — so the two connect with no file juggling in between. This is the single highest-value piece of the whole integration.
It takes two small pieces in conftest.py. First, a hook that records each test's outcome onto the node so the fixture can see whether the test failed:
# conftest.py
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
setattr(item, "rep_" + rep.when, rep)Then the vibe fixture launches Vibium, yields a page to the test, and — after the test — attaches a full-page screenshot to the Allure result if the test failed:
# conftest.py
import os
import allure
import pytest
from vibium import browser_sync as browser
@pytest.fixture
def vibe(request):
headless = os.getenv("HEADLESS", "false") == "true"
instance = browser.launch(headless=headless)
yield instance
rep = getattr(request.node, "rep_call", None)
if rep and rep.failed:
png = instance.screenshot(full_page=True)
allure.attach(
png,
name="failure-screenshot",
attachment_type=allure.attachment_type.PNG,
)
instance.quit()Now every failing Vibium test carries a full-page screenshot inside its Allure entry, one click away from the failure message. A passing test attaches nothing, keeping the report lean. The screenshot(full_page=True) option and its clip variants are documented in the screenshot command.
A test using this fixture stays completely ordinary — it never mentions Allure at all:
def test_login_shows_dashboard(vibe):
vibe.go("https://app.example.com/login")
vibe.find(label="Email").type("user@example.com")
vibe.find(label="Password").type("secret123")
vibe.find(role="button", text="Sign in").click()
assert vibe.find("h1").text() == "Dashboard"Because find() auto-waits for actionability, the assertion runs against a settled page, so a failure means a real defect — and the attached screenshot shows you exactly what the page looked like when it broke. For the full login flow, see automate login with Vibium.
How do I add Allure steps around Vibium actions?
Wrap meaningful Vibium actions in Allure step blocks so the report reads as a human-readable timeline instead of one opaque test body. A step becomes a collapsible node in the Allure view; when a test fails, the failed step is highlighted, pointing you straight at the browser action that broke rather than making you re-read the whole test.
Use the with allure.step() context manager inline, or the @allure.step decorator on reusable helpers:
import allure
def test_checkout_flow(vibe):
with allure.step("Open the product page"):
vibe.go("https://shop.example.com/product/42")
with allure.step("Add the item to the cart"):
vibe.find(role="button", text="Add to cart").click()
with allure.step("Go to checkout and verify the total"):
vibe.find(role="link", text="Checkout").click()
assert vibe.find(".order-total").text() == "$42.00"Each with block is one row in the report timeline, labelled in plain English. This pairs especially well with page objects: decorate the page-object methods with @allure.step, and every call your test makes to login() or add_to_cart() shows up as a named step automatically.
import allure
class LoginPage:
def __init__(self, vibe):
self.vibe = vibe
@allure.step("Log in as {email}")
def login(self, email, password):
self.vibe.find(label="Email").type(email)
self.vibe.find(label="Password").type(password)
self.vibe.find(role="button", text="Sign in").click()The {email} placeholder is interpolated into the step title, so the report shows Log in as user@example.com — real data, not a generic label. The page-object pattern itself is covered in depth in the Page Object Model in Vibium.
How do I add severity, tags, and metadata?
Decorate tests with Allure's metadata so the report can be filtered, sorted, and prioritised — none of which touches Vibium. Allure reads these decorators purely at the runner level, so they layer on top of any Vibium test without changing a single browser call.
import allure
@allure.severity(allure.severity_level.CRITICAL)
@allure.feature("Authentication")
@allure.story("Password login")
def test_login_is_critical_path(vibe):
vibe.go("https://app.example.com/login")
vibe.find(label="Email").type("user@example.com")
vibe.find(label="Password").type("secret123")
vibe.find(role="button", text="Sign in").click()
assert vibe.find("h1").text() == "Dashboard"In the generated report, severity powers the "by severity" graph and lets you answer "did any critical test fail?" at a glance; feature and story group related browser tests into a behaviour tree. Combine these with pytest markers to slice execution — pytest -m smoke --alluredir=allure-results runs and reports only the smoke subset. This is where Allure earns its keep over a plain console run: a stakeholder-readable view of a Vibium suite organised by business behaviour, not by file name.
How do I attach page HTML and console logs, not just screenshots?
Attach whatever page state helps diagnose a failure — Vibium exposes the raw material, and Allure takes any string or bytes. A screenshot shows what broke; the page HTML and console logs often show why. Vibium's content() returns the full page HTML as a string, and you can subscribe to console output with onConsole().
import allure
def attach_page_state(vibe):
# Full rendered HTML of the page at failure time
allure.attach(
vibe.content(),
name="page-html",
attachment_type=allure.attachment_type.HTML,
)Call attach_page_state(vibe) from the same failure branch in your teardown fixture, right after the screenshot. For console output, register a listener when the page is created and buffer the lines, then attach the buffer as plain text on failure:
logs = []
vibe.on_console(lambda entry: logs.append(str(entry)))
# ... run the test ...
allure.attach("\n".join(logs), name="console", attachment_type=allure.attachment_type.TEXT)Now a failed Vibium test in Allure carries three coordinated artifacts — the screenshot, the DOM, and the console — which together usually explain the failure without re-running anything. Capturing console output is covered further in capture console logs.
How do I do this in JavaScript with Jest?
For JS/TS teams, the shape is identical — swap allure-pytest for a Jest Allure adapter and attach Vibium's screenshot bytes in an afterEach that checks the test outcome. Vibium is a normal npm package (npm install vibium), and the async client (require('vibium')) pairs cleanly with Jest's promise handling.
Install the Jest reporter and register it in your Jest config so results are written during the run (the Allure CLI then reads them, exactly as in Python):
npm install --save-dev jest allure-jest
npm install vibiumIn the test file, launch Vibium once, open a fresh page per test, and attach a screenshot when a test fails. Jest 30+ exposes the current test's outcome so you can screenshot only on failure:
const { browser } = require('vibium');
const { attachment } = require('allure-js-commons');
let bro;
let page;
beforeAll(async () => {
bro = await browser.launch({ headless: process.env.HEADLESS === 'true' });
});
afterAll(async () => {
await bro.close();
});
beforeEach(async () => {
page = await bro.newPage();
});
afterEach(async () => {
const failed = expect.getState().numPassingAsserts === 0; // simplistic guard
if (failed) {
const png = await page.screenshot({ fullPage: true });
await attachment('failure-screenshot', png, 'image/png');
}
await page.close();
});
test('the dashboard loads after login', async () => {
await page.go('https://app.example.com/login');
await page.find({ label: 'Email' }).type('user@example.com');
await page.find({ label: 'Password' }).type('secret123');
await page.find({ role: 'button', text: 'Sign in' }).click();
expect(await page.find('h1').text()).toBe('Dashboard');
});The mental model matches pytest exactly: launch the browser in a setup hook, act with Vibium, assert with expect, and attach page.screenshot({ fullPage: true }) bytes in teardown. The attachment(name, body, type) call comes from Allure's runtime library and takes the PNG buffer directly. For the broader Jest wiring, see using Vibium with Jest.
Then generate the report the same way as Python:
npx jest
allure serve allure-resultsHow do I report a Vibium Cucumber suite in Allure?
If you write BDD scenarios, add the CucumberJS Allure adapter and your Gherkin steps become the report's steps for free. Allure's Cucumber integration maps each Given / When / Then to a step node automatically, so a Vibium-backed scenario turns into a readable, business-language report without any manual allure.step() calls.
Your step definitions still call plain Vibium — the reporting is transparent to them:
const { Given, When, Then, After } = require('@cucumber/cucumber');
const { attachment } = require('allure-js-commons');
const { browser } = require('vibium/sync');
Given('I am on the login page', function () {
this.bro = browser.launch({ headless: process.env.HEADLESS === 'true' });
this.page = this.bro.page();
this.page.go('https://app.example.com/login');
});
When('I sign in as {string}', function (email) {
this.page.find({ label: 'Email' }).type(email);
this.page.find({ label: 'Password' }).type('secret123');
this.page.find({ role: 'button', text: 'Sign in' }).click();
});
Then('I should see the dashboard', function () {
if (this.page.find('h1').text() !== 'Dashboard') {
throw new Error('Dashboard did not load');
}
});
After(function () {
const png = this.page.screenshot({ fullPage: true });
attachment('final-screenshot', png, 'image/png');
this.bro.close();
});Each Gherkin line shows up as a labelled step in Allure, and the After hook attaches a Vibium screenshot to every scenario. This gives non-technical stakeholders a living specification report backed by real browser runs. The end-to-end Cucumber wiring is covered in using Vibium with Cucumber BDD.
How do I generate the Allure report in CI/CD?
Run the Vibium suite headless with the Allure adapter, upload the raw allure-results as an artifact, and generate the static HTML report in a follow-up step. Because Vibium reads headless from an environment variable, the exact suite you debug locally is the one CI runs — no separate code path. This slots directly into the pipeline described in Vibium in CI/CD with GitHub Actions.
- name: Run Vibium tests with Allure
env:
HEADLESS: "true"
run: pytest --alluredir=allure-results
- name: Generate Allure report
if: always()
run: |
npm install -g allure-commandline
allure generate allure-results --clean -o allure-report
- name: Upload Allure report
if: always()
uses: actions/upload-artifact@v4
with:
name: allure-report
path: allure-reportThe if: always() on the report steps is essential — you want the report especially when tests fail, so it must run even after a failing test step. allure generate turns the raw results into a self-contained HTML site you download from the run's artifacts (or publish to GitHub Pages for a permanent, linkable dashboard). For the runner and Chrome-library setup this builds on, see CI/CD with GitHub Actions.
To make the report show trends across runs — flaky-test detection, pass-rate history — copy the previous run's history folder into the new allure-results before generating. That is what upgrades Allure from a per-run snapshot into a suite health dashboard over time.
Allure vs. a Vibium trace: which do I use?
Reach for Allure for suite-level reporting and a Vibium trace for single-session debugging — they answer different questions, and the best setup uses both. Allure aggregates every test into one report with history, severity, and attachments; it is what you show a team or attach to a release. A Vibium trace is a granular, frame-by-frame recording of one browser session that you scrub in the trace viewer to see exactly what happened step by step.
| Aspect | Allure Report | Vibium trace |
|---|---|---|
| Scope | Whole suite, all tests | One browser session |
| Best for | Stakeholder reporting, history, trends | Deep debugging of one failure |
| Contents | Pass/fail, severity, steps, attachments | Frame-by-frame timeline + DOM snapshots |
| Audience | Team, managers, release gate | The engineer fixing the bug |
| Persistence | History across runs | A single trace.zip |
They are not mutually exclusive — the strongest workflow records a trace on failure and attaches that trace.zip to the failing test's Allure entry. The report gives you the map (which tests failed, how often); the trace gives you the microscope (what the browser did in the failing run). For everyday flake reduction, the underlying stability comes from Vibium's auto-waiting rather than the report — see flake-free tests.
What are the common gotchas?
Most Vibium-with-Allure friction comes from confusing the two layers or from CI ordering, and each has a one-line fix:
- Empty report / "no results found". You ran the tests without
--alluredir(pytest) or without the reporter registered (Jest/Cucumber), so nothing was written. Always run with the adapter, then pointallure serve/allure generateat the same folder you wrote to. - Screenshots never appear. The attach call is not on the failure path, or you attached a file path instead of bytes. Vibium's
screenshot()returns PNG bytes — pass those bytes directly toallure.attach(..., attachment_type=allure.attachment_type.PNG)or the JSattachment(name, buffer, 'image/png'). - Report is empty in CI even though tests ran. The generate/upload steps were skipped because a test failed. Add
if: always()to the report and upload steps so they run on failure — which is precisely when you need the report. - No history or trends. Allure trends require the
historyfolder from the previous run to be copied into the new results beforeallure generate. Without it, every report is a fresh snapshot. - Steps look empty or unlabeled. You did not wrap actions in
allure.step()(pytest/Jest) — or, in Cucumber, you did not need to, since Gherkin steps map automatically. Add step context managers or@allure.stephelpers for non-BDD suites. - Browser stays open on crash. Teardown did not run because setup raised before the browser was assigned. Launch Vibium as the first thing in the fixture and let the runner's finalization call
quit()/close()so the attach-and-cleanup path always executes.
Treat Vibium as the source of evidence and Allure as the presenter of it, and the integration stays a thin, predictable seam: the runner runs, Vibium acts and screenshots, the adapter writes results, the CLI builds HTML.
The Vibium + Allure checklist
- Install the runner's Allure adapter (
allure-pytest,allure-jest, orallure-cucumberjs) — there is no Vibium-specific plugin to add. - Run tests with results going to
allure-results(--alluredirin pytest; reporter config in JS). - Attach
screenshot(full_page=True)bytes to the report from a teardown hook that fires on failure. - Wrap key Vibium actions in
allure.step()blocks — or let Gherkin steps map automatically in Cucumber. - Add
severity,feature, andstorymetadata so the report is filterable by business behaviour. - Attach page HTML (
content()) and console logs as extra evidence alongside the screenshot. - In CI, run headless, generate with
if: always(), and uploadallure-reportas an artifact. - Copy the previous run's
historyfolder in before generating to unlock trends and flaky-test detection.
Vibium supplies a clean, auto-waiting browser API and the raw evidence — screenshots, HTML, logs; Allure supplies the aggregation, history, and shareable HTML. Connect them through your existing runner's hooks and you get browser reports that are as easy to read as they are to trust.
Next steps
Frequently asked questions
How do I use Vibium with Allure Reports?
Keep Vibium as your browser layer and add Allure as a reporter on top of your test runner. Install allure-pytest (Python) or an Allure adapter for Jest or Cucumber (JS), run your Vibium tests to emit result files, then run allure serve on that folder to open a rich HTML report.
How do I attach a Vibium screenshot to an Allure report?
Vibium's screenshot() and screenshot(full_page=True) return PNG bytes. Pass those bytes straight to allure.attach() with allure.attachment_type.PNG in Python, or the reporter's attachment API in JS. Do it in a teardown hook that fires on failure so every failed test carries a screenshot.
Do I need a special Vibium plugin for Allure?
No. Allure attaches to your test runner, not to Vibium. You install the runner's Allure adapter (allure-pytest, jest-allure2, or allure-cucumberjs), and Vibium simply supplies the browser actions and the screenshot bytes, page HTML, and console logs you attach as evidence.
How do I add custom steps to a Vibium Allure report?
Wrap Vibium actions in Allure step blocks. In Python use the @allure.step decorator on helper functions or the with allure.step() context manager around a find/click. Each step becomes a collapsible node in the report timeline, so a failure points to the exact browser action that broke.
Can I generate an Allure report for Vibium tests in CI?
Yes. Run your Vibium suite headless with the Allure adapter to write allure-results, upload that folder as a CI artifact, then generate static HTML with allure generate. On GitHub Actions the allure-report folder can be published to Pages or kept as a downloadable artifact for every run.
What is the difference between Allure and a Vibium trace?
A Vibium trace is a low-level frame-by-frame recording of one browser session for deep debugging. Allure is a suite-level report aggregating pass/fail, history, severity, and attachments across every test. They complement each other: attach the trace file to the Allure result for the best of both.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
Vibium Best Practices: The Complete Guide
Vibium best practices for reliable browser automation: semantic locators, actionability waits, page objects, isolation, CI, and AI checks.
13 min read→Best PracticesA Complete Vibium CI/CD Pipeline
Build a complete Vibium CI/CD pipeline: install, headless run, parallel shards, artifact capture, and quality gates that block bad merges on every push.
12 min read→Best PracticesData-Driven Testing with Vibium
Data-driven testing with Vibium: feed one browser test many rows from arrays, CSV, or JSON, loop over cases, and keep the automation logic in one place.
15 min read→Best PracticesRun Vibium with Docker Compose
Run Vibium with Docker Compose: orchestrate a headless test service, an app-under-test, mounted artifact volumes, healthchecks, and parallel workers.
15 min read→