Skip to main content

AI-powered Selenium to Playwright migration tool

Project description

QAMigrate

AI-powered test framework migration

PyPI version Python 3.11+ License: MIT

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)

  • @FindBy annotations (id, css, xpath, className, name, linkText)
  • PageFactory.initElements removal
  • WebDriverWait / ExpectedConditions removal (Playwright auto-waits)
  • sendKeys -> fill, clear removal, click direct conversion
  • Actions (hover, drag) -> Playwright equivalents
  • Select dropdowns -> selectOption
  • JavascriptExecutor -> page.evaluate()
  • Alert / iframe handling
  • File uploads -> setInputFiles
  • TestNG -> JUnit 5 lifecycle (@BeforeMethod -> @BeforeEach, etc.)
  • @DataProvider -> @MethodSource
  • Assert.assertEquals / assertTrue -> Playwright assertions
  • ChromeDriver setup -> 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 under src/test or src/
  • --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


Download files

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

Source Distribution

qamigrate-0.3.0.tar.gz (106.2 kB view details)

Uploaded Source

Built Distribution

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

qamigrate-0.3.0-py3-none-any.whl (64.6 kB view details)

Uploaded Python 3

File details

Details for the file qamigrate-0.3.0.tar.gz.

File metadata

  • Download URL: qamigrate-0.3.0.tar.gz
  • Upload date:
  • Size: 106.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for qamigrate-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f14de3aa28a504bdb71ec3be28487118cf24d993807b451d3aefcae112915b9a
MD5 5969b1795f9057421170ab29811095af
BLAKE2b-256 1829711df4f4b78bb5ff30679a295e5e7597f47eed5eeb98a03b6ec97b83c2f9

See more details on using hashes here.

File details

Details for the file qamigrate-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: qamigrate-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 64.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for qamigrate-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c24e7e225a005325dcf0fe9cc543fcbc7978c98f9b44a0f69f95fe1570a8a12b
MD5 5017993fe63505014ee7f3c27390ed22
BLAKE2b-256 001d8baf431c5fb8f882626e9525abafb868594a81904d128fb0098f50c528f6

See more details on using hashes here.

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