petrkindlmann/qa-skillsMIT3 files

Test Migration

>-

Specification
Skill ID
petrkindlmann/qa-skills/test-migration
Publisher
petrkindlmann
Repository
qa-skills
Installs
0
Files
3
License
MIT
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

petrkindlmann/qa-skills/test-migrationInstalls these files
  • SKILL.md
  • references/framework-guides.md
  • references/parallel-ci.md

What this skill tells the agent

<objective> A framework migration is where coverage quietly leaks: twenty old tests become fifteen new ones, a flaky Selenium test is faithfully reproduced as a flaky Playwright test, and the old safety-net suite gets deleted a sprint too early. This skill migrates incrementally with both suites running in CI until parity is proven — so the new suite earns the decommission, you don't just assert it. </objective>


Quick Route

You're going from → toJump toFirst-pass tooling
Selenium → PlaywrightTranslation Patterns + references/framework-guides.mdhand-write; no codemod worth trusting
Cypress → PlaywrightTranslation Patterns + references/framework-guides.mdcy2pw web converter / community CLI (see tooling table)
Protractor → Playwrightreferences/framework-guides.md (urgent — EOL 2023)hand-write; map by.model/by.binding
Jest → Vitestreferences/framework-guides.mdjest.→vi. sed pass, then verify
Mocha → Vitestreferences/framework-guides.mdchai-matcher codemod, then verify
Any path, 100+ testsMigration Workflow + Parallel Running Strategyalways parallel-run in CI

Discovery Questions

Check .agents/qa-project-context.md first. If it exists, use it as context and skip questions already answered there.

Current state:

  • What framework are you migrating from and to? (drives the translation tables and which guide section applies)
  • How many tests exist, and what is the current flakiness/skip rate? (migrating a flaky test reproduces the flakiness; skipped tests may not be worth migrating)
  • Is there a coverage number today? (baseline for the parity track)

Test infrastructure:

  • What supporting infrastructure exists? (page objects, custom commands, fixtures, data factories — these migrate before tests)
  • How is auth/session handled? (login flows are the most common silent-breakage point — see Failure Modes)
  • What CI pipeline runs the tests, and can both frameworks run simultaneously? (parallel-run is non-negotiable)

Constraints:

  • Timeline pressure? (urgent = framework EOL like Protractor; comfortable = modernization)
  • Budget to run both suites during migration? (double CI cost, temporarily)
  • Team's familiarity with the target framework? (training gap drives the workshop/pairing plan)

Core Principles

1. Incremental over big bang

A big-bang rewrite — all tests at once — is the highest-risk approach. It freezes test development for weeks, lands a large batch of unproven tests in one drop, and removes the proven safety net before the replacement exists. Always migrate one test, one module at a time.

2. Parallel run until parity

Run both suites in CI until the new one provides at least the coverage of the old one. The old suite is your safety net; keep it non-blocking but present. Do not decommission until the new suite has caught real regressions over multiple sprints.

3. Migrate highest-value tests first

Start with critical user journeys, frequently-failing tests (which benefit most from a better framework), and high-risk areas. Save low-value tests for last — some are not worth migrating at all, and that's a valid, documented decision.

4. Modernize patterns during migration, don't just translate

Translating a bad Selenium test into a bad Playwright test wastes the opportunity. For each test ask "how would I write this from scratch in the target framework?" — user-facing locators, auto-waiting, fixtures. This applies tenfold to AI-codemod output (see Anti-Patterns).


Migration Workflow

Six phases for a typical multi-sprint migration. Use the checklists inline; heavy code lives in references.

Phase 1 — Audit existing suite (Week 1). Count tests by category, skipped/flaky percentage, coverage if measured, runtime, page-object/utility files, custom plugins, CI stages. Then categorize each test: Critical (revenue flows) → High (core journeys) → Medium (secondary) → Low (admin/edge) → Skip (disabled, duplicate, obsolete). This priority order drives everything downstream.

Phase 2 — Set up target framework (Week 1-2). Install alongside the old one. Create the config (playwright.config.ts / vitest.config.ts), a separate test directory, a non-blocking CI stage, one smoke test to prove the setup, reporters matching the existing format, shared env/secrets.

Phase 3 — Migrate shared infrastructure (Week 2-3). Infrastructure before tests, in this order: base page object/test base → auth helpers → API client helpers → common page objects (nav/header/footer) → data factories → custom assertions → feature-specific page objects (with their tests). Capture `storageState` here so migrated tests skip the login flow.

Phase 4 — Migrate tests by priority (Week 3-8+). Per test: read the old one and understand what it actually verifies → write the new one from scratch with modern patterns (do not line-by-line translate) → run locally green → run in CI green → tag the old one "migrated" (don't delete) → after one sprint of parallel passing, delete the old one.

Phase 5 — Parallel run in CI (throughout). Both suites run every pipeline. The legacy suite stays non-blocking (continue-on-error: true) until the new suite reaches parity; then flip blocking onto the new suite and remove the old job. See references/parallel-ci.md for the full GitHub Actions workflow.

Phase 6 — Decommission old framework (final). Only after parity + stability: all critical/high tests migrated, new suite green in CI for 2+ consecutive sprints, new-suite flakiness ≤ old, coverage comparison shows no regression, team writing new tests in the new framework for 2+ sprints. Then remove old deps from package.json, delete old test files (not just disable), update CI to run only the new suite, update docs.


Automated Migration Tooling

There is no AI magic button. Pick the right first-pass tool by path, then refine by hand using references/framework-guides.md.

ToolUse whenDon't trust for
cy2pw web converter (demo.playwright.dev/cy2pw)Cypress→Playwright, straightforward specs; official, deterministic, browser UIcustom commands, POM conventions, fixture setup
`@11joselu/cypress-to-playwright` (community CLI, npx @11joselu/cypress-to-playwright <dir>)Cypress→Playwright bulk first pass over a directoryanything timing-dependent — review every file
AI agents (Claude Code, Cursor)custom-command and fixture translation, the parts converters can't doa finished test — treat output as a first pass only
Playwright 1.59+ agentic CLI (npx playwright trace, --debug=cli, AI-optimized a11y snapshots)post-migration triage of a failing migrated testthe migration itself — these are debug tools, not converters
Avoid: npx playwright migrate — there is no such built-in Playwright CLI command; the instruction fails at the terminal (verified June 2026). Use cy2pw or the community CLI above.

Golden-reference recipe. Before letting any AI or codemod batch the suite, hand-migrate ONE representative test end to end. Commit it as the team's canonical pattern (e.g. e2e/_golden/login.spec.ts). Feed it back to the AI as a few-shot reference and point human reviewers at it. Every later migration anchors to this file — it's the single highest-leverage tactic for keeping AI output and reviewers consistent.


Translation Patterns

Locator mapping

Old PatternNew Pattern (Playwright)Notes
By.id('submit-btn')page.getByRole('button', { name: 'Submit' })Prefer role-based
By.css('.nav-item.active')page.getByRole('link', { name: 'Dashboard' })Use user-visible text

Use this skill in a project

Open any RiverX project, search the Skills panel for petrkindlmann/qa-skills/test-migration, and install it in one click.

Use this skill