behave-trace

August 5, 2026 · View on GitHub

CI PyPI version Python versions License: MIT Code style: ruff

Trace viewer and step-by-step debugger for Behave BDD.

Captures execution data (steps, statuses, durations, screenshots, DOM snapshots, logs) and visualizes them in a Playwright-inspired web viewer with timeline, filmstrip, per-step detail tabs, before/after DOM diff, and live progress updates.

Quickstart

# 1. Install
pip install behave-trace

# 2. Register the formatter — add to behave.ini in your project root:
#    [behave.formatters]
#    behave-trace = behave_trace.formatter:TraceFormatter

# 3. Capture — run Behave with the formatter
behave --format behave-trace -o trace.json

# 4. Visualize — open the viewer
behave-trace show trace.json

The viewer opens in your browser at http://127.0.0.1:<port> with a dark-themed SPA showing features, scenarios, steps, screenshots, and errors.

How it works

┌──────────┐     ┌──────────────┐     ┌───────────┐     ┌──────────────┐
│  Behave  │────▶│  Formatter   │────▶│  Serializer │────▶│  trace.json  │
│  runner  │     │  (collector) │     │  (JSON)    │     │              │
└──────────┘     └──────────────┘     └───────────┘     └──────┬───────┘

                   ┌────────────────────────────────────────┘

            ┌──────────────┐     ┌──────────────────┐
            │  behave-trace │────▶│  Browser SPA     │
            │  show         │     │  (Alpine.js)     │
            │  (HTTP server)│     │  Dark theme      │
            └──────────────┘     └──────────────────┘

Two-phase model (like Playwright Trace Viewer):

  1. Capture — The TraceFormatter hooks into Behave's formatter API and collects execution events into a Trace data model. Attachments (screenshots, DOM, logs) are captured via attach_screenshot(), attach_dom(), and log() helpers in environment.py.

  2. Visualizebehave-trace show loads the trace JSON, starts a local HTTP server (stdlib only, no dependencies), and opens the viewer SPA in a browser.

Viewer features

  • Visual DOM diff — compare before/after DOM snapshots with added and removed elements highlighted in split, diff, or before/after view modes.
  • Collapse/Expand all — expand or collapse the entire feature tree with one click.
  • Scenario sorting — sort scenarios by name, duration, or status; the selected sort is persisted in localStorage.
  • Feature → Scenario breadcrumb — shows the current feature and scenario above the step list; clicking the feature opens it in the sidebar.
  • Live progress — real-time status updates via Server-Sent Events while tests are running from the viewer.
  • Theme and state persistence — sidebar, sort, and snapshot diff mode are remembered across sessions.
  • Port conflict detection — clear error message instead of hanging when the requested port is already in use (especially on Windows).

Capturing attachments

Add to your environment.py:

from behave_trace import attach_screenshot, attach_dom, attach_text, attach_network, log

def after_step(context, step):
    # Log the current URL after every step
    log(context, f"URL: {context.driver.current_url}")

    if step.status == "failed":
        attach_screenshot(context, context.driver, name="failure.png")
        attach_dom(context, context.driver, name="dom.html")
        log(context, f"Step failed: {step.name}", level="error")

The viewer will show screenshots in the filmstrip and detail tabs, with before/after DOM snapshot toggling. See the attachments guide for the full API.

CLI

# Show trace in browser
behave-trace show trace.json

# Show on specific port, don't open browser
behave-trace show trace.json --port 8080 --no-browser

# Run behave with the trace formatter, then open the viewer
behave-trace run features/

# Run with tags and watch mode
behave-trace run features/ --tags @smoke --watch

# Run from the UI (no initial trace required)
# The viewer opens even if behave fails. A "Run all" button lets you
# execute tests from scratch; selected scenarios can also be re-run.
behave-trace run --no-browser

# Version
behave-trace --version

Run from the UI

behave-trace run starts the viewer even if the initial Behave run fails or no features have been executed yet. The viewer then shows a "Run all" button in the header (and in the empty state) that triggers a fresh Behave execution (POST /api/run).

While tests are running the viewer receives real-time status updates via Server-Sent Events (SSE), and the trace is reloaded automatically when the run finishes. You can also select one or more scenarios and re-run only those with "Run selected".

When watch mode is active, the viewer header shows an "Auto-run" toggle. Enable it to re-execute Behave automatically whenever the watched *.feature or *.py files change (debounced 500ms). Disable it to keep the viewer running and reload the trace manually.

Development

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Or use the Makefile shortcut
make dev

# Lint
ruff check .
ruff format --check .

# Type check
mypy --strict behave_trace

# Run tests
pytest tests/ -v

# E2E tests (meta: Behave testing Behave)
behave tests/e2e/

# Build
python -m build

Requirements

  • Python 3.11+ (tested on 3.11, 3.12, 3.13)
  • behave >= 1.2.6 (installed automatically)
  • No other runtime dependencies (viewer uses only Python stdlib)

Project structure

behave_trace/
    __init__.py          # Public API, formatter registration
    __main__.py          # python -m behave_trace entry point
    formatter.py         # Behave formatter (TraceFormatter)
    collector.py         # Event collector → Trace model
    models.py            # Dataclasses: Trace, Feature, Scenario, Step, etc.
    serializer.py        # JSON load/save
    attach.py            # Attachment helpers (screenshot, DOM, text, network, log)
    runner.py            # Behave runner (subprocess wrapper)
    watcher.py           # File watcher for --watch mode
    utils.py             # Utilities (format_duration, safe_str)
    cli/
        app.py           # argparse CLI with `show` and `run` subcommands
    viewer/
        server.py        # stdlib HTTP server (ThreadingHTTPServer)
        browser.py       # Browser opener (Chrome app mode)
    assets/
        index.html       # SPA shell (Alpine.js from CDN)
        css/viewer.css   # Dark theme styles
        js/viewer.js     # Alpine.js component logic

Documentation

Full documentation is available at mathiaspaulenko.github.io/behave-trace.

Contributing

Contributions are welcome! See CONTRIBUTING.md for setup, commands, and the release process.

License

MIT — see LICENSE.