Migrate from Playwright to TesterArmyYour Playwright suite,
minus the maintenance tax
TesterArmy tests are plain-English steps executed by an AI agent with vision. Paste one prompt into Claude Code, Cursor, or Codex and it reads your spec files, converts them, and verifies every test against your app.
Takes less than 2 minutes. No credit card required.
Every frontend refactor
is a test refactor too
Playwright is a great automation library, but spec files carry a maintenance tax. The tests fail when your app changes, even when nothing broke.
Selectors break when the UI changes
A renamed data-testid, a redesigned login form, a component library upgrade - none of them are bugs, and all of them turn tests red. The suite fails on changes your users never notice.
waitFor calls accumulate to fight flakiness
Every flaky run gets patched with another waitForSelector, a longer timeout, or a retry. Over time the suite is slower, the timeouts are arbitrary, and nobody remembers which waits are still load-bearing.
Refactoring the frontend means refactoring the tests
Locators live in your spec files, so every markup change ripples into them. A frontend refactor that ships in a day can leave an afternoon of selector updates behind it.
Coverage stalls because every flow costs a spec
Each new journey needs locators, fixtures, and waits written and then maintained. The flows that matter most stay untested because the suite is already expensive to keep green.
What your suite reads like
after the conversion
The user intent in your test() bodies becomes act and assert steps, and the selectors are dropped. This is the same checkout flow in both languages.
test("checkout with saved card", async ({ page }) => {
await page.goto("/products/desk-lamp");
await page.getByTestId("add-to-cart").click();
await page.waitForSelector('[data-testid="cart-count"]');
await page.getByTestId("cart-link").click();
await page.waitForURL("**/cart");
await page.getByRole("button", { name: "Checkout" }).click();
await page.waitForSelector("#payment-form", { timeout: 15000 });
await page.getByLabel("Card ending in 4242").check();
await page.getByTestId("place-order").click();
await expect(page.getByTestId("order-confirmation")).toBeVisible({
timeout: 30000,
});
await expect(page.getByTestId("order-total")).toHaveText("$49.00");
});Selectors, waitFor calls, and timeouts are dropped in conversion. The agent finds elements visually and waits on its own, so a renamed data-testid or a redesigned checkout form does not break anything.
The whole migration
is one prompt
Paste this into your coding agent in the repository that contains your Playwright tests. The agent discovers your config and spec files, creates a TesterArmy project, converts each test(), and verifies every one locally with real exit codes.
Migrate this repository's Playwright test suite to TesterArmy using the
TesterArmy CLI (`ta`). Verify auth first with `ta status --json`, and use
`ta --help` plus subcommand help to discover commands. Prefer --json output.
1. Discover: find playwright.config.* and all spec files (*.spec.ts,
*.spec.js, *.test.ts under the configured testDir). Read the config to
determine the baseURL and any storageState/auth setup projects.
2. Create a TesterArmy project (skip if one exists in `ta projects list`):
echo '{"name":"<repo name>","url":"<baseURL>","projectType":"web"}' | ta projects create --json
3. Save durable context as project memories (category site_structure,
importance high): key routes, the login URL, anything from global-setup
files that future test runs should know.
echo '{"category":"site_structure","title":"...","content":"...","importance":"high"}' | ta memories create --project <projectId> --json
4. Convert each Playwright test() into a TesterArmy test:
- Express the USER INTENT of each action in plain English. Drop all
selectors, locators, waitFor calls, and retries - the TesterArmy agent
finds elements visually and waits on its own.
- page.goto/click/fill/selectOption -> steps with type "act"
- expect(...) assertions -> steps with type "assert"
- login fixtures or storageState setup -> one step with type "login"
- Keep tests focused: 3-10 steps. Split test() bodies that cover
multiple flows into separate tests.
- Skip API-only tests, component tests, and page.route() mocking logic.
Create each test:
echo '{"title":"<test name>","description":"Migrated from <spec file>","steps":[{"title":"Navigate to /login","type":"act"},{"title":"Dashboard loads","type":"assert"}]}' | ta tests create --project <projectId> --json
Step types: act, assert, login, screenshot.
5. Never hardcode passwords in test steps. If specs use env vars or
storageState for auth, tell me which credentials to add and I will run:
echo '{"kind":"login","label":"...","username":"...","password":"..."}' | ta projects credentials-create <projectId> --json
6. Verify: run each migrated test locally with
`ta tests run <testId> --local --url <baseURL> --json` and report results.
Exit code 0 = pass, 1 = fail.
7. Report a summary table: spec file -> TesterArmy test ID -> run result,
plus a list of anything you intentionally skipped and why.Everything you built
has a place to land
Nothing in your suite gets orphaned. Every Playwright concept maps to a TesterArmy equivalent - and the two biggest maintenance burdens, selectors and waits, map to nothing at all.
Playwright and TesterArmy,
row by row
Playwright is an excellent automation library, and for component tests, API tests, and mocked-network work it stays the right tool. This table is about what owning an end-to-end suite costs, and where each side wins.
- Who maintains the testsTesterArmyThe agent finds elements visually and waits on its own, so nobody owns a selector layer.AdvantagePlaywrightYour team owns specs, locators, waits, and fixtures - maintenance scales with UI change.
- What breaks on a UI changeTesterArmyUsually nothing - a renamed data-testid or a redesigned form is invisible to a vision agent.AdvantagePlaywrightEvery test whose locator touched the changed markup, and fixing them is manual work.
- Writing a new testTesterArmy3-10 plain-English steps that anyone on the team can write and review.PlaywrightA spec file with locators, waits, and fixtures, written by someone who knows the codebase.
- Flaky failuresTesterArmyThe agent waits like a human, and every failure has a recording and a step trace.PlaywrightHandled with retries, waitFor calls, and timeouts that accumulate inside the suite.
- Run verdictsTesterArmyThree verdicts - passed, failed, or blocked. Environment and setup stops land in blocked with the reason attached, so the failure count only holds real product failures.AdvantagePlaywrightTwo verdicts. A down environment, expired credentials, and a product bug all land in the same failed bucket to triage by hand.
- License and infrastructureTesterArmyA paid service - the agent, browsers, and infrastructure are included.PlaywrightFree and open source; you run the browsers, CI workers, and retry logic yourself.Advantage
- Mocking and component testsTesterArmyOut of scope - tests run against a real environment instead of mocks.PlaywrightFirst class: page.route(), component testing, and API testing are all built in.Advantage
- Pull request workflowTesterArmyPR testing is built in - runs trigger from GitHub and report back on the pull request.PlaywrightYou wire npx playwright test into CI and maintain the workflow yourself.
- Native mobile appsTesterArmyThe same plain-English tests run on iOS and Android via managed cloud simulators.AdvantagePlaywrightWeb only - native apps need a separate stack like Appium, Maestro, or Detox.
- Entry priceTesterArmyFree trial without a credit card; Hobby is $99 per month with 250 test runs included.Playwright$0 forever - the cost is the engineering time in the rows above.
Facts checked August 2026. Spotted something out of date? Tell us and we will fix it.
From spec files to green runs in four steps
Install the CLI, hand the prompt to your coding agent, and review what comes back. Your Playwright suite keeps running until every migrated test is green.
Point the agent at your repo
Install the TesterArmy CLI and authenticate, then paste the migration prompt into Claude Code, Cursor, or Codex. The agent finds playwright.config.ts, reads the baseURL, and creates a matching web project.
The agent converts every test()
Each spec becomes a test of 3-10 plain-English steps: page actions turn into act steps, expect() calls into assert steps, and storageState auth into a single login step backed by encrypted credentials.
Every migrated test runs locally
The agent verifies each test against your app with ta tests run --local and reports pass or fail through real exit codes, plus a summary of anything it intentionally skipped and why.
Wire the suite into CI
Organize tests into groups and run them on every pull request through group webhooks or ta tests run --group. Delete the old E2E specs once the TesterArmy runs are green.
What comes with you,
what stays behind
Most end-to-end specs translate directly, and the guide is explicit about what does not. Playwright stays in your repo for the jobs it is best at.
When Playwright is still the right call
- You need page.route() network mocking, component tests, or API-only tests - that is Playwright's home turf, and the migration guide says to keep them there.
- Your end-to-end flows must run air-gapped or fully offline - TesterArmy tests run against a real, reachable environment.
- You have engineers who genuinely enjoy owning the suite and your frontend markup rarely churns.
- You depend on heavily parameterized tests where all 50 generated variants matter rather than only the representative cases.
Nothing forces the choice on day one. Migrated tests run alongside your Playwright suite, and the guide's own advice is to delete the E2E specs only once the TesterArmy runs are green.
Frequently Asked Questions
A renamed data-testid
should never cost you an afternoon
Your Playwright suite encodes real knowledge about how your product is supposed to work. The migration keeps that knowledge and retires the machinery around it - the selectors, the waits, the retries - so the next frontend refactor ships without a test refactor behind it.