Mobile and Web on One Platform: Where Unified E2E Coverage Pays
Two suites exist because each framework family assumes a different execution target. The cost arrives at the seam, where revenue flows across surfaces, and neither suite is watching.
Yuvan Sundrani · 18 min read
autosana.ai

TL;DR
- Web frameworks assume a headless browser as the execution target while mobile frameworks assume a device driver, and neither assumption can be relaxed by the framework itself.
- The costly gap is the seam rather than the duplication, since revenue-generating flows routinely begin on one surface and complete on another.
- Deep links are the load-bearing example, because App Links and Universal Links are enforced at the operating system level and fail silently when an association file goes stale.
- Seam failures are quiet by construction, as each suite reports green over the half it owns while the handoff between them goes unobserved.
- Autosana executes the same stated flow against a browser or a real device, so the seam sits inside one system rather than between two.
Why do two separate suites exist at all?
Because the frameworks dominating each domain were built by different communities against different runtime assumptions, and those assumptions are structural rather than stylistic.
The web suite usually runs Playwright or Cypress, both excellent inside their domain, both assuming a browser process as the thing being driven. The mobile suite runs Appium, Espresso, XCUITest or Detox depending on the stack, all assuming a device driver as the thing being driven.
Neither family can cross the boundary, since the assumption sits in the architecture rather than in a configuration file. A browser-targeting framework has no concept of a device under test, and a device-targeting framework has no concept of a headless browser context.
So the split persists, and it persists for a reason that has nothing to do with how any particular team is organised. An engineer on r/ExperiencedDevs made the general observation that architectural constraints masquerade as organisational ones for years before anyone names them correctly, which describes this split accurately.
The duplication that follows is visible and frequently discussed. Two repositories, two sets of conventions, two onboarding paths, two bills. That cost is real and it is also the smaller one.
What exactly is a seam?
A seam is any point where a user flow crosses from one surface to another, so responsibility for the next step transfers between runtimes that separate suites cover.
| Seam Type | Typical Flow | What Breaks |
|---|---|---|
| Deep link | Email or web page opens the application | Link opens a browser rather than the app |
| Authentication handoff | Web login triggers an authenticator app | Token fails to return, session stalls |
| Magic link | Web signup resumes inside the application | Resumption lands on the wrong state |
| Payment redirect | App sends the user to a bank page and back | Return arrives at a recreated activity |
| Notification entry | Push notification opens a specific screen | Deep destination resolves incorrectly |
| Cross-device continuation | Laptop start, phone completion | State fails to synchronise between them |
Each row describes a flow that generates revenue or gates access, and each one is partly covered twice and wholly covered never.
Consider a realistic checkout. It begins on a marketing page in a browser, continues through a magic-link redirect that opens the iOS application, and confirms with a push notification. Three surfaces, two seams. The web suite tests the marketing page and stops at the redirect. The mobile suite tests the application and starts after the redirect. Nothing tests the redirect.
Why are deep links the load-bearing example?
Because they are contractual, enforced by the operating system, and silent when broken.
Android documents the contract through App Links, and Apple documents the equivalent through Universal Links. Both require a file hosted on your web domain that declares which application may claim which paths.
Three properties make this dangerous.
The contract spans two teams. The association file lives on the web domain, usually owned by whoever controls the website, while the claim lives in the application manifest, owned by the mobile team. Neither change triggers review by the other.
Verification happens at install time. The operating system fetches and validates the association, so a file that goes stale after installation leaves existing users working while new installs break, which produces a defect visible only to a population nobody is testing.
Failure degrades rather than errors. A broken App Link opens the browser instead of the application. The user reaches a web page, the page loads, and nothing reports a failure anywhere. The flow completed, and it completed on the wrong surface with worse conversion.
A developer on r/androiddev noted the gap between behaviour observed during development and behaviour on real devices, and association verification sits precisely there, since a debug build frequently bypasses the checks a production install enforces.
Why do seam failures stay quiet?
Four mechanisms, and together they explain why these defects reach production so reliably.
Both dashboards report green. The web suite covered its half successfully and the mobile suite covered its half successfully. Neither is lying, and the product is broken.
The failure degrades to a working path. As above, a broken deep link opens a browser rather than throwing. The user completes something, so monitoring sees traffic rather than errors.
Ownership is ambiguous. A seam defect arrives in a space neither team considers theirs, so triage begins with a conversation about whose problem it is before anyone investigates.
Reproduction requires both surfaces. An engineer debugging it needs a device, a browser, a valid association file and a fresh install, which is enough friction that the ticket ages.
The combined effect is a class of defect that reaches users, persists, and surfaces through conversion metrics softening rather than through alerts firing. That is the most expensive shape a defect can take, since nobody is looking for it.
What do teams do about this today?
Three workarounds appear repeatedly, and each falls short in a predictable way.
Manual seam testing before release. Somebody walks the cross-surface flows by hand on a release candidate. This works, and it stops scaling the moment cadence increases, so it becomes the first thing dropped under pressure.
Contract tests on the association file. A check confirms the file is present, valid and reachable. Genuinely useful and considerably better than nothing, though it verifies the declaration rather than the behaviour, so a correct file paired with a wrong path claim still passes.
Stitching the two suites with shared fixtures. The web suite completes its portion, writes state somewhere, and the mobile suite resumes from it. This approximates the flow and skips the actual handoff, since the application was launched directly by the harness rather than by the operating system resolving a link.
That third approach deserves particular attention, because it looks like seam coverage and omits the mechanism being tested. The operating system's resolution step is the thing that breaks, and launching the application directly bypasses it entirely.
A tester on r/softwaretesting made the broader point that production failures tend to be environmental rather than logical, and a seam is environmental by definition, since it lives in how two systems negotiate rather than in either system's code.
One magic link checkout, traced through both suites
Tracing a real flow shows precisely where coverage stops.
The flow: a customer browsing a marketing page enters an email, receives a magic link, opens it on a phone, lands inside the application already authenticated, and completes a purchase confirmed by push notification.
Steps the web suite covers. Page loads, email field accepts input, submission succeeds, confirmation copy renders. The suite asserts that the email was accepted and stops, because its next action would require a device it has no concept of.
Steps nothing covers. The email arrives with a link. The operating system evaluates that link against the association file hosted on the web domain. It resolves to the application rather than the browser. The application opens on the intended screen. The authentication token transfers and the session is recognised.
Steps the mobile suite covers. Given an authenticated session, the cart renders, payment submits, confirmation appears. The suite begins from a state it created directly, so it assumes everything in the previous paragraph succeeded.
Five distinct operations sit in the uncovered middle, and each fails differently. A stale association file sends the user to the browser. A wrong path claim opens the application on the wrong screen. An expired token lands them on a login page. A notification permission never granted means confirmation never arrives.
Every one of those produces a customer who started a purchase and failed to finish, and every one leaves both dashboards green.
The compounding detail: the mobile suite's convenience is what hides the problem. Creating an authenticated session directly is faster and more reliable than driving the real handoff, so the suite becomes more stable while covering less. Stability and coverage pull in opposite directions precisely at the seam.
Which seams deserve coverage first?
Few teams can cover every seam immediately, so rank them by two properties and work down.
Revenue or access exposure. A seam inside a purchase or a login blocks money or entry, while a seam inside a settings deep link irritates. Rank by what a failure prevents rather than by how often the path runs.
Silence on failure. A seam that errors loudly gets reported by users within hours, whereas a seam degrading to a working-but-wrong path can persist for months. Prioritise the quiet ones, since they are the ones monitoring fails to surface.
Applying both produces a short list for most products:
| Priority | Seam | Why It Ranks Here |
|---|---|---|
| 1 | Magic link or email auth into the application | Blocks access, degrades silently to a browser |
| 2 | Payment redirect and return | Blocks revenue, returns to a recreated state |
| 3 | Push notification entry to a deep destination | Drives re-engagement, resolves incorrectly in quiet ways |
| 4 | Web-to-app handoff for an existing session | Common, usually degrades rather than errors |
| 5 | Cross-device continuation | Lower volume, frequently loud when it fails |
A developer on r/Playwright made the general point that locator and tooling debates distract from the question of what a suite is actually asserting, and seam coverage is the clearest case, since a team can hold an excellent framework discussion while the flow nobody tests continues failing.
One practical note on sequencing. Cover the top seam end to end before broadening, because a single genuinely covered seam teaches the team more about what the handoff involves than five partially covered ones.
What does a unified execution model change?
The response to the two-suite problem arrived as a change in execution rather than as a framework that speaks both protocols.
An agent-based model assumes no particular runtime. It receives a goal, inspects current state, decides an action, executes, observes the result and decides again. The surface it inspects can be a browser tab or a device screen, and the loop is identical.
That independence is what makes one test suite two platforms wide genuinely possible, rather than two suites sharing a dashboard. Provided the flow describes intent rather than encoding interface structure, the same flow executes against whichever surface it reaches, including surfaces it reaches partway through.
The consequence for seams is the whole argument. A flow that crosses from browser to application stays one flow inside one system, so the handoff is executed and observed rather than assumed. Ownership collapses to one team, one dashboard and one integration, which also dissolves the triage ambiguity described above.
Where the unified model still has limits
Four, stated plainly.
Per-interaction overhead exceeds a dedicated framework. Playwright remains faster for a large suite of predictable web interactions, and Espresso remains faster for pure native Android checks. Teams running thousands of stable interactions inside a tight window against one runtime should keep the framework built for that runtime.
Agents can decide incorrectly. Ambiguous interfaces and thin context permit a wrong path, which is why verification beyond the visible screen matters for a deciding system.
Unit and component layers stay where they are. This argument concerns end-to-end coverage, and the layers beneath belong in code that names elements deliberately.
Device and browser supply bounds breadth. A unified model removes the architectural barrier rather than the infrastructure one.
The honest summary: unification earns its place where flows cross surfaces, and a product living entirely on one surface gains considerably less from it.
How does Autosana cover both surfaces?
Autosana is an AI-native E2E testing agent, and both surfaces sit under one model rather than under two integrations.
Applications are registered through a single apps object. Web coverage runs across Chrome, Firefox, Edge and Chromium per the web testing documentation, while mobile coverage executes against hosted real devices. Flows are written in natural language and remain the same object regardless of which surface they execute against, which is the property that lets one flow span a handoff.
Real devices matter disproportionately here. Association verification, operating-system link resolution and notification delivery are behaviours that exist on hardware and stay absent from a generic image, so testing a deep link on an emulator frequently validates something other than what ships.
Results arrive through the GitHub integration with session replay attached, which matters at a seam because the question is always which surface received the handoff, and watching it answers that immediately. Flows are invocable over MCP.
The limits listed above apply as written, and deciding which cross-surface flows matter remains product judgement belonging to your team.
Where to start
List the flows that generate revenue or gate access, then mark every point where the user crosses surfaces. Most teams find between three and six seams, and most find that none of them is covered end to end by either suite.
Then take the single highest-value seam and test it the hard way once, manually, on a fresh install with a production association file. That one exercise usually reveals whether the contract is intact, and it establishes the baseline the automated version needs to reproduce.
FAQ
Why do teams run separate web and mobile test suites?
Because web frameworks assume a browser process as the execution target while mobile frameworks assume a device driver, and that assumption sits in the architecture rather than in configuration, so neither family can cross the boundary.
What is a seam in end-to-end testing?
Any point where a user flow crosses from one surface to another, transferring responsibility between runtimes that separate suites cover. Deep links, authentication handoffs, magic links and payment redirects are the common examples.
Why do deep link failures go unnoticed?
They degrade rather than error. A broken App Link opens the browser instead of the application, so the user reaches a working page, monitoring sees traffic rather than failures, and both test suites report green over their own halves.
Can you test App Links and Universal Links automatically?
Behaviour testing requires the operating system to resolve the link on a real install, since a harness launching the application directly bypasses the resolution step that actually breaks. Contract tests on the association file complement this rather than replacing it.
Does sharing fixtures between two suites cover the seam?
No. That approach approximates the flow while skipping the handoff, because the application gets launched by the harness rather than by the operating system resolving a link, and resolution is the mechanism that fails.
Who owns a seam defect?
Ambiguity here is part of the problem, since the association file sits with whoever owns the web domain and the claim sits with the mobile team. Triage frequently begins with a conversation about ownership before investigation starts.
Is a unified platform always better than two specialist suites?
No. Dedicated frameworks remain faster for large volumes of predictable interactions against one runtime. Unification earns its place where flows cross surfaces, and a single-surface product gains considerably less.
How does Autosana execute one flow across two surfaces?
Flows state intent rather than encoding interface structure, so the same flow object executes against a browser or a real device. A handoff therefore stays inside one system, where it gets executed and observed rather than assumed.
.png)