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.1.tar.gz (111.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.1-py3-none-any.whl (66.6 kB view details)

Uploaded Python 3

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

Hashes for qamigrate-0.3.1.tar.gz
Algorithm Hash digest
SHA256 a23a83bcf7d9c8b56e7a5bbfdd5ca8723d6b37c59eac3ed0ba69ce0bf7655496
MD5 dd45710691b9d943b448298463482f9e
BLAKE2b-256 022939db6b8ebba374a633ac4cd7999019c6db72f6924825e7e2d7e806cd5626

See more details on using hashes here.

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

Hashes for qamigrate-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9b804e05fea0fb98f30cef45b2f2027826b75ce26bac8b0e50c725c5332cc8af
MD5 4874283301bedea00ca343bcd24f5fc4
BLAKE2b-256 4ad0ec10c1aae028cedddf977ef31baf2609d6df31ee1c519e426cea85b9e5da

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