AI-powered Selenium to Playwright migration tool
Project description
QAMigrate
AI-powered test framework migration
A QATonic Innovations product.
QAMigrate converts test suites between frameworks automatically. It parses your code with Tree-sitter, generates equivalent code with Claude, and produces a full migration report with per-file diffs, confidence scores, and estimated time savings.
Today: Selenium Java -> Playwright Java Next: Cypress -> Playwright, TestNG -> JUnit 5, RestAssured -> Karate, and more.
Why QAMigrate
You don't just get generated code. You get evidence:
- Per-file diffs -- every pattern we touched, why, and side-by-side before/after
- Confidence score -- how sure we are about each file, 0 to 100
- Batch report -- HTML, JSON, and Markdown; share with your team
- Time-saved estimate -- how many hours of manual work you avoided
- Dry-run mode -- preview what would change without calling the LLM
What it does
Give it a Selenium file:
// Selenium
@FindBy(id = "username")
private WebElement usernameInput;
public void login(String user, String pass) {
usernameInput.clear();
usernameInput.sendKeys(user);
passwordInput.sendKeys(pass);
wait.until(ExpectedConditions.elementToBeClickable(loginButton));
loginButton.click();
}
Get Playwright back:
// Playwright (generated by QAMigrate)
private final Locator usernameInput;
public LoginPage(Page page) {
this.usernameInput = page.locator("#username");
}
public void login(String user, String pass) {
usernameInput.fill(user);
passwordInput.fill(pass);
loginButton.click(); // Playwright auto-waits
}
Supported patterns (Selenium -> Playwright Java)
@FindByannotations (id, css, xpath, className, name, linkText)PageFactory.initElementsremovalWebDriverWait/ExpectedConditionsremoval (Playwright auto-waits)sendKeys->fill,clearremoval,clickdirect conversionActions(hover, drag) -> Playwright equivalentsSelectdropdowns ->selectOptionJavascriptExecutor->page.evaluate()- Alert / iframe handling
- File uploads ->
setInputFiles - TestNG -> JUnit 5 lifecycle (
@BeforeMethod->@BeforeEach, etc.) @DataProvider->@MethodSourceAssert.assertEquals/assertTrue-> Playwright assertionsChromeDriversetup ->Playwright.create()+browser.newContext()- Base class inheritance preservation
Quick start
Prerequisites
- Python 3.11+
- Java 17+ (for compilation validation; optional — see
compiler.skip) - Anthropic API key
Install
pip install qamigrate
Configure
echo "ANTHROPIC_API_KEY=sk-ant-your-key" > .env
Initialize (once per project)
# Auto-injects Playwright + JUnit 5 into your pom.xml so compile-check works.
qamigrate init --project ./my-selenium-project --yes
Migrate
# Dry-run: see what would happen without calling the LLM
qamigrate migrate --all --project ./my-selenium-project --dry-run
# Migrate a single file
qamigrate migrate src/test/java/LoginPage.java --project ./my-selenium-project
# Migrate the whole project with batch compile + report (recommended)
qamigrate migrate --all --project ./my-selenium-project --report ./qamigrate-report
Output goes to playwright/ subdirectories next to each original file.
If you use --report <dir>, you get report.html, report.json, and report.md.
Example report summary
QAMigrate - Migrating 7 file(s)
-> [1/7] BaseTest.java
OK src/.../playwright/BaseTest.java (14.1s, 75% confidence)
-> [2/7] LoginPage.java
OK src/.../playwright/LoginPage.java (17.2s, 75% confidence)
...
Files 7 / 7
Patterns handled 149
Avg confidence 75%
Time 105.3s
Est. hours saved ~37.2
Report written:
HTML: ./qamigrate-report/report.html
JSON: ./qamigrate-report/report.json
Markdown: ./qamigrate-report/report.md
CLI commands
| Command | Description |
|---|---|
qamigrate init |
Initialize QAMigrate in a project |
qamigrate scan |
Analyze codebase, detect patterns, show complexity |
qamigrate migrate |
Convert files to the target framework |
Common flags for migrate:
<file>— migrate a single file--all, -a— migrate all Java files undersrc/testorsrc/--dry-run— analyze only, no LLM calls, no writes--report <dir>— write HTML + JSON + Markdown report--project, -p <path>— project root (default: current dir)
How it works
Scanner (Tree-sitter) Deterministic AST parsing, pattern detection
|
Coder (Claude API) Generates Playwright Java via structured output
|
Compiler (javac) Validates generated code compiles
|
Fixer (rules + Claude) Fixes compilation errors, retries up to 3x
|
Report Records everything that happened
Plain Python — no LangChain, no graph framework, no agents-of-agents. Each step is a clean module you can read in 5 minutes.
Configuration
Optional qamigrate.yaml in your project root:
pipeline:
max_retries: 3
coder:
model: "claude-sonnet-4-20250514"
max_tokens: 8192
compiler:
build_tool: "maven" # or "gradle"
java_version: "17"
skip: false # set true when Playwright JARs aren't on classpath
scanner:
exclude_patterns:
- "**/target/**"
- "**/build/**"
- "**/playwright/**"
You can also use environment variables with the QAMIGRATE_ prefix:
export QAMIGRATE_COMPILER__SKIP=true # skip compilation check
export QAMIGRATE_PIPELINE__MAX_RETRIES=5 # more retries
Python API
from qamigrate.agents.pipeline import run_migration
from qamigrate.core.config import QAMigrateConfig
from qamigrate.core.report import MigrationReport
config = QAMigrateConfig()
report = MigrationReport()
result = run_migration(
file_path=Path("src/test/java/LoginPage.java"),
project_path=Path("."),
config=config,
)
if result.record:
report.add(result.record)
report.finish()
report.write_html(Path("./report.html"))
Development
pip install -e ".[dev]"
pytest tests -v
ruff check src tests
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 qamigrate-0.3.1.tar.gz.
File metadata
- Download URL: qamigrate-0.3.1.tar.gz
- Upload date:
- Size: 111.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a23a83bcf7d9c8b56e7a5bbfdd5ca8723d6b37c59eac3ed0ba69ce0bf7655496
|
|
| MD5 |
dd45710691b9d943b448298463482f9e
|
|
| BLAKE2b-256 |
022939db6b8ebba374a633ac4cd7999019c6db72f6924825e7e2d7e806cd5626
|
File details
Details for the file qamigrate-0.3.1-py3-none-any.whl.
File metadata
- Download URL: qamigrate-0.3.1-py3-none-any.whl
- Upload date:
- Size: 66.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b804e05fea0fb98f30cef45b2f2027826b75ce26bac8b0e50c725c5332cc8af
|
|
| MD5 |
4874283301bedea00ca343bcd24f5fc4
|
|
| BLAKE2b-256 |
4ad0ec10c1aae028cedddf977ef31baf2609d6df31ee1c519e426cea85b9e5da
|