Back to Blog
E2E TestingPlaywrightTest StrategyQA ArchitectureTest Automation

Your E2E Framework Needs Fewer Features, Not More

The promise of a 'next generation' E2E framework often leads teams down a rabbit hole of complexity and fragility. True progress isn't about more advanced locators or self-healing selectors; it's about ruthlessly narrowing the scope of what E2E tests are actually responsible for.

October 12, 2026
8 min read
RS
Raju Shanigarapu

Most teams building "next generation" E2E frameworks are solving the wrong problem. They pour engineering effort into making inherently bad tests more reliable or faster, instead of fundamentally questioning why those tests exist at all. This architectural misstep leads to a bloated, slow, and untrustworthy suite that drains resources and ultimately fails to provide genuine production confidence.

The conventional wisdom dictates E2E tests are the ultimate safety net, the final gate before production. This mindset encourages teams to push more and more scenarios into the UI layer, believing that if a user can do it, an E2E test must replicate it. My experience at Mendix, building complex enterprise applications, hammered home the point that this exhaustive approach quickly becomes a liability. You end up with a high-maintenance, flaky beast that everyone dreads.

Your Framework Isn't Failing, Your Strategy Is

The allure of a new framework like Playwright 1.4x, Cypress, or Appium is strong. Developers see powerful APIs, robust browser automation, and claim it will fix all their E2E woes. What they often overlook is that the framework is just a tool. If your underlying test strategy is flawed, a new tool merely allows you to build flawed tests faster.

Teams often migrate from Selenium to Playwright, for instance, but carry over the same anti-patterns: monolithic tests that cover too much, direct database manipulation for setup, and reliance on external, unstable services. This isn't "next generation"; it's just a faster way to build the same house of cards. A truly next-generation E2E framework isn't defined by its features, but by its restraint.

Stop Testing Everything Through The UI

The single biggest mistake teams make is attempting to validate business logic and data integrity through the UI. The user interface is the most expensive, slowest, and flakiest layer in your stack to test. Every interaction involves network latency, rendering engine quirks, and brittle locators.

Complex calculations, API contract validations, and data persistence checks belong at lower levels of the testing pyramid. Unit tests for functions, integration tests for service boundaries, and contract tests for API interactions are orders of magnitude faster, more stable, and cheaper to maintain. Before working on broadband device software at Liberty Global, the importance of isolating UI tests from backend instability was paramount. E2E tests should be a thin veneer, verifying that the critical user flows connect the pieces correctly, not validating the pieces themselves.

The Illusion of "End-to-End" Without Isolation

Many E2E tests claim to be "end-to-end" but are actually integration tests in disguise, hitting real external services like payment gateways, email providers, or third-party APIs. When these external services are unavailable, return unexpected data, or rate-limit your tests, your E2E suite becomes a chaotic mess of intermittent failures. This provides zero actionable feedback about your application's actual health.

True E2E confidence comes from control, not from relying on the internet's whims. This means isolating your E2E tests from external dependencies. Tools like WireMock are invaluable for simulating API responses, allowing your tests to run deterministically. Playwright's network interception capabilities achieve the same for client-side applications, providing mock data directly to the browser. Without this isolation, your green builds are a lie, masking real issues or failing due to factors entirely outside your application's control. While tools like Testcontainers excel at providing isolated environments for true integration tests, they are not a substitute for strategic API mocking within E2E.

Build For Real User Journeys, Not Developer Fantasies

The scope of your E2E tests should be dictated by your users' most critical, high-value journeys, not by every feature a developer implements. Most teams write E2E tests based on what they think users will do, or worse, what's easy to automate. This leads to tests for obscure edge cases that are rarely encountered, while critical paths remain fragile.

Leverage analytics, user telemetry, and product usage data to identify the 5-10 most important user flows. These are the workflows that, if broken, would have the most severe impact on your business. Your E2E suite should be laser-focused on these specific paths, verifying that the UI allows users to complete them successfully and that the application responds as expected. Anything else is noise and a drain on resources.

Code Example: Orchestrating a Focused E2E Test

Here’s how you build a robust, focused E2E test using Playwright 1.4x and Python, specifically designed to isolate the UI from backend API instability. We use Playwright's page.route() to intercept and mock API calls, ensuring our test runs deterministically regardless of the actual backend service state.

import pytest
from playwright.sync_api import Page, expect
import json

# This fixture sets up Playwright's network interception for the duration of each test function.
# It ensures that specific API calls are mocked, providing consistent responses.
@pytest.fixture(scope="function", autouse=True)
def setup_mock_api(page: Page):
    # Intercept GET requests to the user profile API and return a mock admin user.
    # This ensures the UI renders the correct elements for an admin.
    page.route("**/api/users/current", lambda route: route.fulfill(
        status=200,
        content_type="application/json",
        body=json.dumps({"username": "qa_user", "roles": ["admin"]})
    ))

    # Intercept POST requests to the products API and return a successful creation response.
    # This prevents the test from failing due to actual database writes or backend processing.
    page.route("**/api/products", lambda route: route.fulfill(
        status=201, # HTTP 201 Created
        content_type="application/json",
        body=json.dumps({"id": "prod-123", "name": "Next Gen Widget", "status": "created"})
    ) if route.request.method == "POST" else route.continue_()) # Only mock POST, let other methods continue

    # For any other routes not explicitly mocked, let them continue to the real network.
    # This is important to allow fetching of static assets or other unmocked APIs.
    yield page # Yield control to the test function

    # Teardown: Playwright context usually handles unrouting automatically after the test.

# A focused E2E test demonstrating an admin user creating a product.
# This test verifies the UI flow and its immediate feedback, relying on mocked API responses.
def test_admin_can_create_product(page: Page):
    # Navigate to the product administration page.
    page.goto("http://localhost:3000/admin/products")

    # Assert that the page title is correct, indicating successful navigation and rendering.
    expect(page.locator("h1")).to_have_text("Product Management")

    # Fill out the product creation form.
    page.get_by_label("Product Name").fill("Next Gen Widget")
    page.get_by_label("Price").fill("99.99")

    # Click the button to create the product.
    # The POST /api/products call will be intercepted and mocked by our fixture.
    page.get_by_role("button", name="Create Product").click()

    # Assertions based on UI feedback after the *mocked* successful API call.
    # We expect a success toast message and a redirect to the new product's detail page.
    expect(page.locator(".toast-success")).to_have_text("Product 'Next Gen Widget' created successfully!")
    expect(page.url).to_contain("/admin/products/prod-123") # Verify URL redirect

This test doesn't care if the actual /api/products endpoint is up or down, or if the database is responding slowly. It solely verifies that the UI correctly handles an admin user creating a product, given a predictable API response. This makes the test fast, stable, and truly focused on the "end-user experience" of the UI layer, not the intricacies of the backend.

Where This Breaks Down

This highly isolated, focused E2E strategy is powerful, but it's not a silver bullet. The primary challenge lies in the discipline required. It demands strong communication between frontend and backend teams to define and maintain API contracts for effective mocking. If API contracts change without corresponding mock updates, your E2E tests will still pass, but your application will break in production.

This approach also doesn't completely replace some level of full-stack integration testing. You still need a few, highly stable integration tests that verify the interaction between your frontend, backend, and critical external services (without mocks) in a controlled environment. However, these full-stack tests should be very limited in number and scope, serving as a final sanity check, not your primary feedback mechanism. Over-mocking can create a false sense of security if the mocks diverge too far from reality without proper contract testing in place.

The Real Cost of a Bloated E2E Suite

The alternative—a large, unisolated E2E suite—comes with a steep price. Flaky tests erode developer trust, leading to ignored failures and green builds that hide real problems. Slow CI pipelines block deployments and reduce developer velocity. High maintenance costs consume valuable engineering time that could be spent on features or more effective testing.

Furthermore, a bloated E2E suite gives a false sense of security. Because so much is being tested at the UI layer, teams neglect robust unit and integration testing, creating a brittle foundation. When a bug does slip through, it's often more difficult to diagnose because the E2E test fails ambiguously, without pinpointing the root cause in the stack. Your "next generation" E2E framework must, first and foremost, be a minimalist framework.

This week, identify your single most critical user journey. Rewrite that E2E test using Playwright 1.4x and page.route() to mock all external API calls, focusing solely on the UI's behavior.

Want to build systems that work this way?

I work with QA engineers and engineering teams on automation architecture, framework audits, and AI-powered quality systems.

Get posts like this in your inbox

No fluff. Sharp takes on QA, AI, and engineering — once a week.

Sent with MailerLite. See the privacy policy.