Most enterprise teams I talk to have the same problem. A large Selenium suite that works, a clear sense that Playwright is the better tool for new development, and no budget to rewrite everything at once. Stopping regression coverage for six months to migrate isn't an option when the suite is what gates releases.
At work I'm leading exactly this migration: a VB.NET Selenium codebase moving to C#, on an adapter pattern that implements both a Selenium driver and a Playwright driver behind one interface. I can't share the code. I can share the architecture and what I've learned running it.
The adapter is the strategy
The core idea is that test logic should never know which browser automation engine is underneath it. A test says "navigate here, find this element, assert this text." The adapter decides whether that becomes a Selenium WebDriver call or a Playwright Page call.
That gives the team three things at once:
- Existing tests keep running on Selenium while they're ported, so coverage never drops.
- New tests are written against the adapter and can run on either driver from day one.
- Cross-browser coverage comes from the driver layer, not from rewriting tests.
The last one matters more than it sounds. On this site's own suite, three browser projects run the same specs because Playwright abstracts the engine. The adapter brings that property to a codebase that predates Playwright entirely.
Two migrations, one track
The language move, VB.NET to C#, and the driver move, Selenium toward Playwright, are separate concerns that happen to share a schedule. Keeping them separate in the design is what makes the project tractable. The adapter interface is defined in C#. Ported tests target the interface. Which driver executes them is configuration. A test can be migrated to C# and still run on Selenium the day it lands, which means the port is reviewable on its own without also being a behavior change.
Page objects across driver generations
The page object model survived the transition, and it's the reason the migration is possible at all. A page object that exposes intent, "submit the form," "open the details panel," instead of exposing locators and waits, ports cleanly because its interface is about the application rather than the driver.
The page objects that didn't port cleanly were the ones that had leaked driver calls into test logic over the years. Those got refactored first, and the refactor was the same work whether or not the migration ever happened: it just made the leakage visible.
Where assistants help
Migration work has a shape assistants are good at: a large volume of similar transformations with a known target pattern. Converting a VB.NET page object to the C# adapter interface is boilerplate once the first one exists. Generating the Playwright implementation of an adapter method when the Selenium one is written is pattern matching. Proposing deterministic waits to replace timing-based ones is a review task with a clear rule.
So the assistants do that, inside the team's version-controlled Rules and Profiles, with the adapter's interface as the contract they can't change. What they don't do is decide what the interface is, which tests port first, or when a driver switch is safe. Those decisions are thoroughly human, and they're the ones that determine whether the migration succeeds.
The concrete effect has been on maintenance throughput. Script maintenance and enhancement work moves faster when everyone, people and assistants, starts from the same prompt patterns and the same interface.
Backward compatibility is non-negotiable
The rule I've held hardest: at no point during the migration does the release gate get weaker. Every ported test has to pass on the original driver before it's allowed to run on the new one. Every adapter method has to have parity tests proving both implementations behave the same on the same page. The suite that gates releases today is the suite that gates them tomorrow, plus whatever has been added.
That rule slows the migration down. It's also why the team trusts it.
Measuring progress
Coverage that hasn't dropped. The count of tests running through the adapter versus directly against Selenium. Defect escape rate holding steady or improving. Execution time, because the Playwright path is faster and the improvement is a visible reward for porting. None of those are vanity numbers. Each one would show a problem early.
Why this matters beyond QA
Enterprise AI adoption tends to stall on codebases like this one: large, old, and load-bearing. The adapter pattern is what makes such a codebase safe to change at speed, by assistants or by people. Decoupling the volatile layer from the stable one, keeping the gate strong, and letting the boring transformations be automated inside a contract. That's the same shape as every other piece of AI-assisted engineering I do. This one just happens to be written in C#.