AI-powered multi-agent framework to plan, generate and heal Selenium Python tests (pytest + pytest-bdd)
Project description
Selenium Python AI Agent ๐ค
AI-powered multi-agent framework that plans, generates, and heals Selenium Python tests automatically โ working the way Playwright's test agents do, but for Selenium. Supports Anthropic Claude and OpenAI ChatGPT as LLM backends.
๐ง How It Works โ 3 Agents
Your Instruction
โ
โผ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ PLANNER โโโโโโโถโ GENERATOR โโโโโโโถโ HEALER โ
โ โ โ โ โ โ
โ live DOM scanโ โ POM code fromโ โ run โ rescan โ
โ (+ optional โ โ plan, self- โ โ live DOM โ โ
โ site explore)โ โ verified โ โ fix โ verify โ
โ โ specs/*.md โ โ (syntax + โ โ (final fix โ
โ specs/*.json โ architecture)โ โ always re-run)โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
Every agent uses real DOM locators โ a real browser is opened headlessly before planning and healing, so the LLM never guesses selectors.
Plans are reviewable artifacts โ like Playwright's planner agent, the Planner saves a human-readable Markdown plan plus a machine-readable JSON plan to specs/. Review or edit the plan, then generate from it.
โก Quick Start
1. Install
pip install selenium-python-ai-agent
pip install python-dotenv # recommended โ load keys from .env
2. Set API Keys
Create a .env file in your project root (git-ignored automatically):
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
3. One-Time Config Setup
Works with any OpenAI or Anthropic model โ pick the one that fits your budget and complexity:
# any of these (or any other model your API key can access):
selenium-agent config --provider openai --model gpt-4o-mini # fast & cheap
selenium-agent config --provider openai --model gpt-4o # strong all-rounder
selenium-agent config --provider openai --model gpt-5 # most intelligent (reasoning)
selenium-agent config --provider anthropic --model claude-sonnet-5 # strong all-rounder
selenium-agent config --provider anthropic --model claude-fable-5 # most intelligent
selenium-agent config --base-url https://www.saucedemo.com # default URL for all runs
selenium-agent config --headless # (--no-headless to turn off)
selenium-agent config --show # verify saved config
๐ก For simple flows
gpt-4o-mini/claude-haiku-4-5are fine; for multi-page/complex flows usegpt-4o,gpt-5,claude-sonnet-5orclaude-fable-5โ noticeably better plans and one-shot code.
4. Generate & Run Tests
Describe any workflow on any web app in plain English โ the examples below are just examples.
Two ways to give the target URL โ a one-off flag, or save it once in config:
# Option A: pass the URL for this run (it is also saved to config for next time)
selenium-agent "add an item to cart and checkout as guest" --url https://your-app.com
# Option B: save it once, then never pass it again
selenium-agent config --base-url https://your-app.com
selenium-agent "test the login page" # uses saved base_url
# Full flow: plan โ generate โ heal (default)
selenium-agent "test the login page"
# Plan first, review, then generate (Playwright-agents workflow)
selenium-agent --plan-only "test the checkout flow"
# โ specs/test-the-checkout-flow.md (read/edit this)
# โ specs/test-the-checkout-flow.json
selenium-agent --from-plan specs/test-the-checkout-flow.json
# Something broke later (UI changed, locator died)? Heal it:
selenium-agent --heal-only generated_tests/tests/test_checkout.py
๐๏ธ Works Inside YOUR Existing Framework
Most teams don't start from scratch โ they already have a Selenium project. Point the agent at it with --project and it adapts to your structure instead of imposing its own:
# First, see what the scanner detects about your project (read-only).
# The path is SAVED to config โ you never need to repeat it.
selenium-agent --scan /path/to/your/project
# From now on every run fits into it automatically:
selenium-agent "test the invoice creation flow"
selenium-agent "test the user permissions page"
# Manage the saved project:
selenium-agent config --project /other/project # switch
selenium-agent config --project none # clear
The built-in ProjectScanner detects and follows:
| What it detects | Effect on generated code |
|---|---|
Your folder layout (pages/, page_objects/, tests/, e2e/, โฆ) |
Files are written into your folders |
Your base page class (BasePage, PageBase, AbstractPage, โฆ) |
Page objects extend your class, with your import path |
| Your test framework (pytest / pytest-bdd / unittest) | Matching test style |
Your naming conventions (test_login.py vs LoginTest.py, login_page.py vs LoginPage.py) |
Same naming |
Your conftest.py and driver fixture |
Reused โ not overwritten |
| Your import style (absolute/relative) and sample code | Generated code follows your style |
--heal-only also works directly on your existing test files โ the healer auto-discovers the page objects your tests import.
๐ค Claude Code Integration โ init-agents
The Selenium equivalent of npx playwright init-agents --loop=claude:
selenium-agent init-agents # into current project
selenium-agent init-agents --project /path/to/project
This installs three Claude Code subagents:
.claude/agents/selenium-test-planner.md โ plans tests, saves specs/
.claude/agents/selenium-test-generator.md โ generates code from specs/
.claude/agents/selenium-test-healer.md โ runs, debugs & fixes tests
Then, inside Claude Code:
"use selenium-test-planner to plan tests for https://www.saucedemo.com" "use selenium-test-generator to generate the tests from specs/login.json" "use selenium-test-healer to fix tests/test_login.py"
๐ All Commands
Generate Tests (Main Command)
The instruction is free-form natural language โ it works for any application and any workflow, not just login pages. The planner opens your URL in a real browser and builds the plan from your app's actual DOM.
selenium-agent "<describe any workflow to test>" --url <your-app-url>
Example instructions (any app, any flow):
selenium-agent "test the login page" # uses saved config + URL
selenium-agent "search for 'laptop' and verify results show prices" --url https://demo.opencart.com
selenium-agent "register a new account and verify the welcome banner" --url https://myapp.internal
selenium-agent "fill the contact form and verify the thank-you message" --url https://mycompany.com/contact
selenium-agent "login as admin, create an invoice and verify it appears in the list" --url https://erp.mycompany.com
selenium-agent "add two items to cart, remove one, then checkout as guest" --url https://shop.example.org
Flags (combine with any instruction):
selenium-agent "..." --url https://staging.myapp.com # override saved URL once (also saved)
selenium-agent "..." --no-heal # generate only, skip healing
selenium-agent "..." --mode bdd # Gherkin .feature files
selenium-agent "..." --headless # no visible browser
selenium-agent "..." --explore 3 # explore up to 3 more pages while planning
selenium-agent "..." --output-dir my_tests/ # custom output folder
selenium-agent "..." --project /path/to/project # fit into YOUR existing framework
selenium-agent "..." --model gpt-5 # override model for this run
selenium-agent "..." --max-retries 8 # more healer attempts (default: 5)
--plan-only โ Preview & Persist the Test Plan
selenium-agent --plan-only "test the login page"
selenium-agent --plan-only "end-to-end purchase flow with checkout and logout" --explore 2
Saves specs/<slug>.md (human-readable) + specs/<slug>.json (generator input),
built from a real DOM scan โ scenarios, locators, wait strategies.
Smart planning includes:
- Live DOM scan first โ selectors come from your actual page, never guessed
- SPA-aware scanning โ polls until React/Vue/Angular apps finish rendering (boot animations included)
- Relevance-ranked site exploration (
--explore N) โ follows the links that match your instruction (a sign-up flow explores the register page, a checkout flow explores the cart), multi-hop: pages linked from explored pages are reachable too - Selector uniqueness verification โ every CSS/XPath is counted against the live DOM; ambiguous selectors are scoped to a unique ancestor or flagged, so the wrong twin element is never picked
- Text & value elements captured โ labels, displayed values, status badges get locators too (for "read the X shown on the page" workflows)
- Dropdown options captured โ
<select>option texts are scanned so planned test data matches real options - CAPTCHA / bot-protection detection โ reported honestly as a blocker instead of doomed retries (never bypassed)
--from-plan โ Generate From a Saved/Edited Plan
selenium-agent --from-plan specs/test-the-login-page.json
selenium-agent --from-plan specs/test-the-login-page.json --no-heal
selenium-agent --from-plan specs/test-the-login-page.json --headless
Smart generation includes:
- Deterministic scaffolding โ the
driverfixture lives in a framework-generatedconftest.py, never LLM-written (an entire class of collection errors is impossible by construction) - Self-verification before saving โ every file is syntax-checked (
ast), architecture-checked (noBy/locators/DriverFactory in test files) and completeness-checked (page objects AND tests present), with one automatic LLM repair round - Unique runtime test data โ entity-creating flows (sign-ups, records) get uuid-based emails/names, and strong unique passwords (never
Password@123-style patterns that breach-list validators reject) - Complete form filling โ "fill the form" means every scanned input/select, not just the fields named in the instruction
--heal-only โ Fix Existing Tests
selenium-agent --heal-only generated_tests/tests/test_login.py
# Heal tests living in YOUR project (page objects auto-discovered from imports)
selenium-agent --heal-only src/tests/test_checkout.py --project /path/to/your/project
# Heal one test only (other tests preserved verbatim)
selenium-agent --heal-only generated_tests/tests/test_login.py \
--test test_login_locked_out_user
# pytest -k syntax works too
selenium-agent --heal-only generated_tests/tests/test_login.py \
--test "locked_out or invalid_password"
# Stubborn failure? Give it more rounds and a stronger model
selenium-agent --heal-only generated_tests/tests/test_login.py --max-retries 8 --model gpt-5
Smart healing includes:
- Failure-time diagnostics โ on every failure the run reports
FAILURE_URL(the exact page the browser was on),FAILURE_ERRORS(visible alert/validation messages) andFAILURE_PAGE_TEXT, so the healer debugs from evidence, not guesses - Live DOM re-scan of the failing page(s) โ locator fixes come from ground truth, grouped per page so locators are never borrowed from the wrong page
- Selenium-specific error classification (SeleniumErrorMap) before the LLM is asked โ including SPA patterns like "the URL never changes, assert an in-page indicator instead"
- Every fix is validated (syntax + architecture) โ a broken fix never overwrites a working file
- The final fix is always verified with a test run (never "fixed and hoped")
- Pure-Python failures (imports, collection) skip browser scans โ attempts are spent where they matter
- Missing locators added to page objects (never to test files);
Byimports stripped from tests - Targeted mode restores any test functions the LLM accidentally drops
- CAPTCHA-blocked flows are reported as blocked instead of endlessly "fixed"
--scan โ Inspect an Existing Project
selenium-agent --scan /path/to/existing/project
Detects folder layout, base page class, test framework, driver setup, naming conventions and import style โ so generated code fits into the project.
๐ก๏ธ Battle-Hardened BasePage
Generated code runs on a BasePage that survives real-world DOM messiness:
- Duplicate-element tolerance โ when one selector matches several elements (desktop form + hidden mobile drawer with the same ids, wrapper sharing its id with the input inside), it picks the displayed, editable, in-viewport one instead of crashing
- Fuzzy dropdown matching โ
select_by_text("United States")still works when the option is literally"United States of America (the)" safe_type()โ typing verified after entry, with a JS + React-event fallback for stubborn SPA inputs- Fluent waits everywhere โ
fluent_wait(locator, 'visible'|'clickable'|'present'|'invisible'); notime.sleep()anywhere - Forgiving locator input โ a raw selector string accidentally passed where a locator tuple belongs is auto-normalized instead of crashing
๐๏ธ Generated Output Structure
specs/
โโโ test-the-login-page.md โ reviewable test plan (Planner output)
โโโ test-the-login-page.json โ machine-readable plan (Generator input)
generated_tests/
โโโ pages/
โ โโโ login_page.py โ Page Object (locators live here)
โโโ tests/
โ โโโ test_login.py โ pytest test file (no raw locators)
โโโ conftest.py โ framework-provided driver fixture + failure diagnostics
Architecture enforced by the agents:
- Locators are always class constants in page objects:
LOGIN_BUTTON = (By.CSS_SELECTOR, '[data-test="login-button"]') - Test files reference by name:
page.LOGIN_BUTTONโ noBy, no raw strings, no DriverFactory - One page object per page โ multi-page flows get one class each
- All waits via
fluent_wait(locator, condition)โ notime.sleep() wait_for_url()after every navigation,page.safe_type()for React/SPA forms
๐ข Enterprise-Grade Reliability
| Concern | What the framework does |
|---|---|
| LLM flakiness | Automatic retries with exponential backoff on rate limits / 5xx / timeouts |
| Malformed LLM JSON | Native JSON modes (OpenAI json_object, Anthropic prefill) + robust extraction: fences, prose, trailing commas, truncation repair |
| Broken generated code | Every file ast-validated + architecture-validated before saving; automatic repair round |
| Broken "fixes" | Healer rejects invalid fixes โ never overwrites working files |
| Unverified fixes | Final heal attempt always followed by a verification test run |
| Guessed selectors | Live DOM scans with per-selector uniqueness verification |
| Client-side apps | SPA-aware scan polling โ waits for React/Vue/Angular to actually render |
| Flaky duplicate DOM | BasePage prefers displayed/editable/in-viewport elements among duplicates |
| Colliding test data | Runtime-unique emails/names + strong unique passwords by rule |
| Bot protection | CAPTCHA detected and reported โ never bypassed, never blindly retried |
| Hung test runs | pytest executed with a hard timeout |
| Existing projects | ProjectScanner detects your BasePage, layout & conventions; code fits in |
| Reasoning models | OpenAI gpt-5*/o* token budgets handled (reasoning tokens accounted for) |
๐ง All CLI Flags Reference
| Flag | Description | Default |
|---|---|---|
--provider |
anthropic or openai |
from config |
--model |
Any model of that provider, for this run | from config |
--api-key |
API key (prefer .env instead) | env var |
--url |
Base URL for this run (also saved to config) | from config |
--mode |
pytest or bdd |
from config (pytest) |
--headless |
Headless browser | from config (false) |
--explore N |
Explore up to N extra same-origin pages while planning (relevance-ranked, multi-hop) | 0 |
--output-dir |
Where to save generated files | generated_tests |
--project |
Existing project path (saved to config โ set once) | from config |
--max-retries |
Healer fix attempts | 5 |
--no-heal |
Skip healing after codegen | false |
--plan-only |
Save + show plan, no code | false |
--from-plan FILE |
Generate from saved plan JSON | โ |
--heal-only FILE |
Heal specific file(s) | โ |
--test TEST_NAME |
Target specific test (with --heal-only) |
โ |
--scan PATH |
Scan existing project structure | โ |
--version |
Show version | โ |
Subcommands: selenium-agent config โฆ, selenium-agent init-agents โฆ, selenium-agent help
๐ค Supported Models
Any chat model from OpenAI or Anthropic works โ pass it via --model or save it with selenium-agent config --model <name>. Recommendations:
| Provider | Model | Best for |
|---|---|---|
| OpenAI | gpt-4o-mini |
Simple flows, lowest cost |
| OpenAI | gpt-4o |
Strong default for real projects |
| OpenAI | gpt-5 / gpt-5-mini |
Complex multi-page flows (reasoning models โ token budgets handled automatically) |
| Anthropic | claude-fable-5 |
Most intelligent โ hardest multi-page flows |
| Anthropic | claude-opus-4-8 |
Complex flows, high quality |
| Anthropic | claude-sonnet-5 |
Strong default for real projects |
| Anthropic | claude-haiku-4-5-20251001 |
Simple flows, lowest cost |
๐ฆ Requirements
- Python 3.9+
- Chrome browser installed
- API key from Anthropic or OpenAI
๐ค Contributing
PRs welcome! See CONTRIBUTING.md
๐ License
MIT โ free to use, modify, distribute.
Built with โค๏ธ by Ankit Tripathi
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file selenium_python_ai_agent-0.2.2.tar.gz.
File metadata
- Download URL: selenium_python_ai_agent-0.2.2.tar.gz
- Upload date:
- Size: 84.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74e64735393d7d7543ca18df6b109553ea64c5b47ed026cab984bba689f5665f
|
|
| MD5 |
e4f0da6ba9efb470c0b6f6039800a4cf
|
|
| BLAKE2b-256 |
c7674179ba2b9369cfc378a9585ccae4a5c701d7fcf79fe8e2fa60ce0fdd65a3
|
File details
Details for the file selenium_python_ai_agent-0.2.2-py3-none-any.whl.
File metadata
- Download URL: selenium_python_ai_agent-0.2.2-py3-none-any.whl
- Upload date:
- Size: 84.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cacf96cd2d2fa36aa777da4bc964260163ac3298d2fe4bd71a1465de56f0d0bd
|
|
| MD5 |
cfa36aa53549148856eaa85a0523e77e
|
|
| BLAKE2b-256 |
b0c2948f2207df80f62b8c95bb9641ac520be68ac43d4ed4163998eacb853951
|