June 17, 2026
How to Use AI to Convert Selenium Tests to Playwright
Learn how to convert Selenium tests to Playwright with AI, what usually migrates cleanly, what still needs manual work, and when Endtest is a better migration target.
If you have a mature Selenium suite, the urge to migrate is usually not about fashion. It is about friction. Flaky waits, brittle locators, slow browser setup, awkward parallelization, and a growing pile of page object code all push teams toward a newer tool. Playwright is often the destination, because it is fast, modern, and much nicer to work with for many browser automation use cases. The catch is that a Selenium-to-Playwright rewrite can become a large engineering project if you treat it like a line-by-line translation.
That is where AI can help. Used well, AI can convert Selenium tests to Playwright with AI support, draft the first version of the new test, and surface the places where your old assumptions no longer hold. Used poorly, it can generate code that looks plausible, but still preserves the same bad patterns that made your Selenium suite painful in the first place.
In this article, I will show how I approach migration as an SDET, what AI can realistically automate, what still needs human review, and how to decide whether rewriting into Playwright is actually the right target. I will also explain why some teams are better off moving to an agentic platform like Endtest instead of creating another large codebase that they will need to maintain for the next five years.
What AI is good at during a Selenium to Playwright migration
The best use of AI here is not magic code generation, it is translation assistance. A Selenium suite usually contains a lot of repetitive structure that can be mapped mechanically:
- finding the equivalent Playwright APIs
- converting explicit waits into web-first assertions or locator waits
- replacing brittle CSS/XPath patterns where possible
- turning page object methods into simpler test steps
- updating fixture setup, teardown, and browser context code
- spotting duplicated utility helpers that can be collapsed
A good prompt can take a Selenium test and produce a first-pass Playwright version that is structurally close to correct. For example, if I give Claude or another code model a Selenium test with WebDriverWait, findElement, and page object methods, I can usually get a pretty decent draft of a Playwright test() function, plus notes about selectors and assertions that still need validation.
The key is to think of AI as an accelerator, not an automatic migration button.
If the Selenium test is already badly designed, AI will usually reproduce the design flaw in a new framework with more modern syntax.
Before you migrate, classify the tests
This is the part teams skip, and it is why migrations drag on.
Not every Selenium test deserves the same migration strategy. I usually split the suite into four buckets:
1. High-value user journeys
These are the tests that matter most to product risk, checkout, signup, permissions, billing, critical admin flows. They are worth carefully porting to Playwright because you will want them stable and readable.
2. Broad regression coverage
These are many smaller tests that cover combinations of roles, states, and validations. AI is very useful here because the patterns repeat and the translation work is tedious.
3. Legacy or low-signal tests
If a test has not failed in months, nobody trusts it, or the business flow is obsolete, do not migrate it just because it exists. Retire it.
4. Framework baggage
These are helpers, custom wrappers, and page object layers that exist mostly because Selenium encouraged them. Some of them should be redesigned instead of translated.
If you start with this classification, you can ask AI to generate a migration plan, not just code. That is much more useful than dumping an entire repository into a model and hoping for the best.
A practical workflow to convert Selenium tests to Playwright with AI
Here is the workflow I recommend when I need to migrate real tests.
Step 1: Extract one representative test
Pick a test that is:
- important enough to matter
- not overly dependent on obscure environment setup
- representative of your suite patterns
- not already full of random sleeps and test smells
A simple Selenium Python example might look like this:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def test_login(driver): driver.get(“https://example.com/login”) driver.find_element(By.ID, “email”).send_keys(“user@example.com”) driver.find_element(By.ID, “password”).send_keys(“secret”) driver.find_element(By.CSS_SELECTOR, “button[type=’submit’]”).click() WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, “h1.dashboard”)) ) assert driver.find_element(By.CSS_SELECTOR, “h1.dashboard”).text == “Dashboard”
That is small, but it already contains the basic migration surface: navigation, typing, clicking, waiting, and assertion.
Step 2: Ask AI to translate behavior, not syntax
A prompt that works better than “convert this code to Playwright” is something like:
- convert this Selenium test to Playwright
- preserve behavior and assertions
- replace explicit waits with Playwright best practices
- simplify selectors where possible
- point out any assumptions that need validation
- keep the result in one Playwright test file
A decent Playwright draft for the example above might become:
import { test, expect } from '@playwright/test';
test('login', async ({ page }) => {
await page.goto('https://example.com/login');
await page.locator('#email').fill('user@example.com');
await page.locator('#password').fill('secret');
await page.locator('button[type="submit"]').click();
await expect(page.locator('h1.dashboard')).toHaveText('Dashboard');
});
That is the easy part. The hard part is checking whether the migrated test is actually robust.
Step 3: Review selectors and wait strategy
This is where AI commonly helps, but also where it can be wrong.
Selenium suites often lean on XPath and explicit waits because that was the path of least resistance. Playwright gives you better primitives, but only if you use them correctly. If AI mechanically converts every Selenium selector into an equivalent Playwright CSS selector, you may end up with a fragile new suite that still breaks when DOM structure changes.
In review, I look for:
page.locator('div > span:nth-child(2)'), which is usually too structural- assertions on text that changes with localization or A/B tests
- waits that can be replaced by
expect(locator).toBeVisible()ortoHaveText() - hard-coded timeouts imported from the Selenium era
- test setup that still assumes global browser state
For Playwright, prefer role-based locators when possible:
typescript
await page.getByRole('button', { name: 'Submit' }).click();
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
When AI suggests this kind of locator, that is a good sign. When it does not, you should steer it.
Step 4: Translate shared helpers with care
Large Selenium suites usually hide complexity in helper methods such as loginAsAdmin(), waitForAjax(), or custom wrapper classes around WebDriver.
AI can translate these helpers, but you should decide whether the helper should exist at all in Playwright. Often the migration is a chance to flatten abstractions. Playwright already provides a more coherent test runner, fixtures, and assertions. You do not necessarily need to rebuild a Selenium-style utility layer.
A useful rule is this, if a helper makes the test clearer, keep it. If it exists only because Selenium needed it, remove it during migration.
Where AI usually gets stuck
Even strong models can only infer so much from a single file. The remaining migration pain usually shows up in the same places.
1. Authentication and test data setup
Selenium tests often assume pre-seeded users, browser cookies, or side effects from previous tests. Playwright is happier when tests are isolated and explicit. AI can rewrite the login flow, but it cannot fully resolve your test-data strategy.
If your current suite uses shared accounts or depends on an external seed job, address that before you finish the migration.
2. Frames, tabs, popups, and downloads
These are all supported in Playwright, but the code shape changes enough that AI can make mistakes.
For example, a Selenium test that switches windows may need a different Playwright approach using page.waitForEvent('popup') or multiple contexts. Do not accept a blind translation here without running it.
3. Timing assumptions
A lot of Selenium code contains accidental sleeps or waits for “just long enough.” Playwright’s auto-waiting can remove some of that, but it does not eliminate application-level race conditions. If the app is genuinely asynchronous, you still need good assertions around the real condition.
4. Cross-test contamination
Some Selenium suites rely on shared driver instances or mutated global config. That is dangerous in Playwright because parallel execution exposes hidden coupling. AI can translate the code, but it will not detect every hidden dependency between tests.
5. Framework-specific hooks
If your Selenium stack includes custom reporting, environment bootstrapping, or a homegrown retry system, AI can generate a starting point, but the final integration work is still on you.
A better prompt pattern for Claude or similar tools
When people say “Claude convert Selenium to Playwright,” they often mean “give me code.” That is too shallow. I get better results by giving the model context in layers.
Here is the prompt structure I use:
- target language and framework, for example Playwright with TypeScript
- Selenium source code
- any page object or helper class definitions the test uses
- notes about preferred locator style, for example role-based locators first
- notes about known app behavior, such as if the dashboard appears after login
- request for a brief migration review listing risky areas
The review part matters. I want the model to say things like:
- this selector may be unstable because it uses layout structure
- this wait can be replaced with a text assertion
- this helper probably depends on shared auth state
That output is often more valuable than the first-pass code.
Example: migrating a page object-based Selenium test
Page objects are common in Selenium, and they are where migrations can get bloated.
Imagine a simplified page object:
python class LoginPage: def init(self, driver): self.driver = driver
def login(self, email, password):
self.driver.find_element(By.ID, "email").send_keys(email)
self.driver.find_element(By.ID, "password").send_keys(password)
self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
AI may translate this into a Playwright class, but in many cases I would ask whether the class still adds value. If the only thing the page object does is wrap locators, I often prefer a smaller test or a fixture.
A Playwright-style helper might be enough:
typescript
async function login(page, email: string, password: string) {
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password').fill(password);
await page.getByRole('button', { name: 'Sign in' }).click();
}
That keeps the migration grounded in behavior, not framework ceremony.
What to validate after AI generates the draft
I always run migrated tests through the same checklist.
Functional correctness
Does the test still verify the same outcome? A translation can accidentally weaken the assertion. For example, “dashboard heading is visible” is not always equivalent to “dashboard heading text is exactly Dashboard.”
Locator quality
Does the new test use stable selectors? If the answer is no, your migration just replaced old brittleness with new brittleness.
Isolation
Can this test run alone, repeatedly, and in parallel? If not, fix the design before scaling the migration.
Readability
Would a teammate understand this in six months? If AI produced a clever but opaque function chain, simplify it.
Runtime behavior in CI
Does the test pass locally but fail in CI? That usually means a hidden wait issue, data dependency, or environment mismatch. Do not blame the tool too quickly.
The migration is not complete when the test compiles. It is complete when it is stable in your CI pipeline.
When Playwright is the right destination, and when it is not
I like Playwright. I use it often. But “migrate to Playwright” is not automatically the best answer for every team.
Playwright is a strong choice if you want:
- a code-first test framework with excellent browser automation ergonomics
- better waiting semantics than older Selenium patterns
- modern browser context isolation
- strong support for TypeScript and JavaScript-heavy teams
- a path toward cleaner E2E tests without too much abstraction
But if your team is not eager to own another growing test codebase, the migration cost may not be worth it. This is especially true for organizations with:
- a large legacy Selenium suite
- mixed technical skill across QA, product, and development
- limited maintenance time
- a desire to reduce framework ownership instead of replacing one framework with another
That is one reason I think teams should evaluate Endtest vs Selenium and Endtest vs Playwright before committing to a rewrite. Endtest is an agentic AI Test automation platform, so the migration target is not “new codebase, new maintenance burden.” With AI Test Import, Endtest can bring existing Selenium, Playwright, Cypress, JSON, or CSV tests into its cloud workflow, and the output remains editable, which matters if you want gradual migration rather than a big bang rewrite.
Why Endtest can be a better migration target than Playwright for some teams
This is the practical part CTOs care about.
If you migrate from Selenium to Playwright, you are still ending up with code that someone has to own, review, refactor, and keep aligned with application changes. That is fine for teams that want a code-centric automation strategy. It is not ideal for teams that mainly want less maintenance.
Endtest takes a different approach. Its AI Test Creation Agent can turn plain-English scenarios into editable Endtest tests, and its import flow can migrate existing Selenium tests with selector translation, step mapping, and assertion conversion handled by the platform. In other words, the migration target is a shared, agentic workflow, not a new pile of framework code.
That can be the better choice when:
- your Selenium suite is large and expensive to rewrite
- you want to bring tests over incrementally
- non-developers need to inspect or help author tests
- you want to avoid owning a second custom framework layer
- your priority is maintainability, not framework purity
If that sounds like your organization, I would read Endtest’s migration from Selenium docs before starting a Playwright rewrite.
A decision framework I use on real teams
Here is the question I ask before any migration starts:
Do we want to own test code, or do we want to reduce the amount of code we own?
If the answer is “own the code,” then AI-assisted Selenium-to-Playwright migration makes sense. Use AI to accelerate conversion, then use human review to improve locators, assertions, and architecture.
If the answer is “reduce code ownership,” then a code rewrite is probably the wrong destination. In that case, an agentic platform like Endtest is worth serious consideration, because you can migrate tests with AI Import and continue editing the results in a platform-native way rather than growing a new framework tree.
A realistic migration checklist
Before I call a migration successful, I want to see the following:
- high-value flows ported first, not the easiest ones
- selectors improved, not just translated
- waits converted to assertions where possible
- test data strategy documented
- parallel execution verified in CI
- flaky tests triaged before the suite is expanded
- old Selenium tests retired or fenced off to prevent duplicate maintenance
Final thoughts
AI is genuinely useful for migrating Selenium tests to Playwright, but only if you treat it as a sharp assistant, not an oracle. It can save hours on translation work, surface design problems, and help you move faster through repetitive test assets. What it cannot do is decide whether your old suite should exist in the first place, or whether your team wants to keep living inside a code-heavy automation stack.
If you want the flexibility and control of Playwright, AI can get you there faster, and it can help you avoid the most obvious migration mistakes. If you want to leave Selenium behind without inheriting another large codebase, then Endtest is worth a look as a more practical migration target, especially for teams that care about maintainability, shared authoring, and incremental adoption.
Either way, do not measure success by how much code AI can generate. Measure it by how much test maintenance you remove from your life.