Skip to main content

Self-healing test framework for Playwright. Your tests survive app changes.

Project description

🍞 Breadcrumb
Self-Healing Playwright Tests

CI License Python Status


What is this?

Your Playwright test clicks #login-btn. A developer renames it to .auth-button. The button still works — but your test crashes.

Breadcrumb fixes this automatically. On the first run it fingerprints every element your test touches. When a locator breaks later, it finds the right element using the text, position, tag, DOM path, and other signals it stored — then carries on. No cloud. No API keys. One line of code.

Beyond healing, Breadcrumb also:

  • Tracks flaky tests — measures per-test flip rates and auto-quarantines chronic failures
  • Generates tests — crawls a page and writes Page Object Model + pytest skeletons for you
  • Exposes MCP tools — lets Claude and other AI assistants query your healing database directly

Install

pip install pytest-breadcrumb[playwright]
playwright install chromium

Requires Python 3.10+.

Optional extras:

Extra Installs
pip install pytest-breadcrumb[playwright] Playwright wrapper
pip install pytest-breadcrumb[mcp] MCP server (for AI assistants)
pip install pytest-breadcrumb[ai] Ollama integration for AI test generation
pip install pytest-breadcrumb[playwright,ai,mcp] Full feature set

Install from source (development):

git clone https://github.com/FaraazSuffla/breadcrumb.git
cd breadcrumb
pip install -e ".[dev]"
playwright install chromium

Quick Start

Option 1 — Standalone script

Wrap your Playwright page with crumb() and pass a test_id:

from playwright.sync_api import sync_playwright
from breadcrumb import crumb

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = crumb(browser.new_page(), test_id="test_login")  # one-line wrapper

    page.goto("https://myapp.com")
    page.locator("#login-btn").click()   # Run 1: fingerprinted and saved
    # Developer renames #login-btn to .auth-button ...
    page.locator("#login-btn").click()   # Run 2: healed automatically ✅

Note: test_id is required for standalone usage. It tells Breadcrumb which fingerprint to look up when a locator breaks. The pytest fixture sets it automatically.

Option 2 — pytest (recommended)

Use the built-in heal_page fixture — test_id is set from the test name automatically:

# test_login.py
def test_login(heal_page):
    heal_page.goto("https://myapp.com")
    heal_page.locator("#login-btn").click()
    assert heal_page.locator(".welcome").is_visible()
pytest --breadcrumb --breadcrumb-report

How it works

1. Learn — On the first run, Breadcrumb fingerprints every element your test touches: tag name, text content, ID, CSS classes, attributes, DOM path, sibling context, and visual position. Fingerprints are saved to .breadcrumb.db (local SQLite, WAL mode).

2. Heal — When a locator breaks on a later run, Breadcrumb scans the live page, scores every visible element against the stored fingerprint using seven similarity signals, and retries with the best match. If nothing scores above 0.5 confidence, the test fails normally — Breadcrumb never silently picks a wrong element.

3. Report — Every heal event is logged with the original locator, new locator, and confidence score. Breadcrumb tracks per-test pass/fail rates and auto-quarantines tests that flip repeatedly.


Features

Feature Status
Self-healing locators (Playwright wrapper) ✅ Working
pytest plugin (heal_page fixture) ✅ Working
Flaky test tracker + auto-quarantine ✅ Working
Console / HTML / JSON reports ✅ Working
CLI (report, doctor, init, generate) ✅ Working
AI test generation (Page Object Models) ✅ Working
MCP server + docs site ✅ Working

CLI

# View healing summary
breadcrumb report
breadcrumb report --format html          # → report.html dashboard
breadcrumb report --format json          # → report.json
breadcrumb report --days 7               # limit to last 7 days

# Check database health
breadcrumb doctor

# Generate tests from a live page
breadcrumb generate https://myapp.com
breadcrumb generate https://myapp.com --out ./tests

# Scaffold a new project
breadcrumb init --name myproject         # creates conftest.py + tests/test_sample.py

# Start the MCP server (requires pip install pytest-breadcrumb[mcp])
breadcrumb mcp
breadcrumb mcp --db /path/to/.breadcrumb.db

Flaky Test Tracking

Every test run is recorded. Breadcrumb computes a flip rate (how often a test alternates pass → fail) and classifies each test automatically:

Tier Flip rate What happens
Stable 0% Normal
Intermittent 0–20% Flagged in report
Flaky 20–50% Auto-quarantined
Chronic > 50% Quarantined + doctor warning

Quarantined tests are skipped automatically until they recover. View the full breakdown:

breadcrumb report --format html   # opens a dashboard with per-test status
breadcrumb doctor                 # shows quarantine count and stale fingerprints

MCP / AI Tools

Breadcrumb exposes 7 tools via MCP, letting Claude and other AI assistants query your healing database directly.

Install:

pip install pytest-breadcrumb[mcp]

Configure Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "breadcrumb": {
      "command": "breadcrumb",
      "args": ["mcp"]
    }
  }
}

Available tools:

Tool Description
breadcrumb_stats Total fingerprint + heal-event counts
breadcrumb_report Full healing report for the last N days
breadcrumb_doctor DB health check (schema, stale fingerprints, quarantine)
breadcrumb_healing_events Recent heal events, filterable by test name
breadcrumb_flaky_tests Per-test flakiness classification
breadcrumb_generate_tests Crawl a URL and return POM + pytest source code
breadcrumb_list_fingerprints All stored element fingerprints

Security

The generate command crawls arbitrary web pages and embeds HTML attribute values into generated Python source files. Breadcrumb protects against this in three ways:

  • CSS selector injectionid, class, and name attributes are stripped to word characters and hyphens only. data-testid and text values are backslash-escaped for CSS quoted strings.
  • Code injection — selectors are embedded using Python's repr(), which safely escapes all quote variants, backslashes, and newlines before writing them into generated .py files.
  • Prompt injection — when Ollama is used, page names and element data are stripped of non-printable characters and capped in length before being embedded in LLM prompts.

No generated file can execute or exfiltrate data beyond what Playwright already does.


Benchmarks

Healing a typical page (30–100 elements) adds under 15 ms per broken locator.

Operation Time
Single similarity score ~0.009 ms
Heal over 100 candidates ~2 ms
Heal over 1,000 candidates ~14 ms
Fingerprint write (SQLite) ~0.29 ms
Fingerprint read ~0.006 ms

Common Pitfalls

Healing not working? Make sure you pass test_id when using the standalone wrapper:

# Wrong — healing silently disabled
page = crumb(browser.new_page())

# Right — healing works
page = crumb(browser.new_page(), test_id="test_login")

The pytest heal_page fixture sets test_id automatically. This only affects standalone usage.

Database in the wrong place? .breadcrumb.db is created in the directory you run Python from. To set a fixed location:

page = crumb(browser.new_page(), test_id="test_login", db_path="./tests/.breadcrumb.db")

Confidence too low? If your app has significant DOM changes between runs, lower the threshold:

page = crumb(browser.new_page(), test_id="test_login", threshold=0.4)

The default is 0.5. Going below 0.3 risks false positives.


Contributing

git clone https://github.com/FaraazSuffla/breadcrumb.git
cd breadcrumb
pip install -e ".[dev]"
playwright install chromium
pre-commit install
pytest

See CONTRIBUTING.md for details.


License

BSD-3-Clause. See LICENSE.

Acknowledgments

  • Scrapling (BSD License) — adaptive element tracking inspiration
  • Playwright (Apache-2.0) — browser automation engine

Designed & crafted with ❤️ by Faraaz Suffla

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_breadcrumb-0.1.0a2.tar.gz (74.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_breadcrumb-0.1.0a2-py3-none-any.whl (53.6 kB view details)

Uploaded Python 3

File details

Details for the file pytest_breadcrumb-0.1.0a2.tar.gz.

File metadata

  • Download URL: pytest_breadcrumb-0.1.0a2.tar.gz
  • Upload date:
  • Size: 74.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pytest_breadcrumb-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 a26b5edc701db9747f4d197a13c37ff514b3810198e090c611d5140c69acfd7f
MD5 0ab30a9ebcb3d6afea7734e0b81b47e1
BLAKE2b-256 e8bfa05386a8f5bee3d6dd260f166428fb211e47867da1efb36a96ef778d113a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_breadcrumb-0.1.0a2.tar.gz:

Publisher: publish.yml on FaraazSuffla/breadcrumb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytest_breadcrumb-0.1.0a2-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_breadcrumb-0.1.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 9ddef756949d2b46f8a3887f47fbd5ad3792b75f9143e93e729efc546315a6de
MD5 41799b5df679bb0c68d1a5d3f7ed30da
BLAKE2b-256 310a331e3cd01b0218a8e2900e5760b822925e1c6ff4aff1f123b558cff4d52a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_breadcrumb-0.1.0a2-py3-none-any.whl:

Publisher: publish.yml on FaraazSuffla/breadcrumb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page