Skip to main content
End-to-end testing workflow showing a user journey across frontend, backend, APIs and connected systems
Sten Laidoner
Sten Laidoner|July 28, 2026|Reading time: 14 min

What Is End-to-End Testing?

End-to-end testing checks whether complete user journeys work across the frontend, backend, APIs, data, integrations and connected systems.

Software teams often test individual parts of a product separately.

A developer may confirm that the login function accepts valid credentials. An API test may confirm that the authentication endpoint returns the correct response. A component test may confirm that the login button enters its loading state when clicked.

All of those tests can pass while the actual login journey still fails.

The frontend might store the session incorrectly. The application may redirect the user to the wrong workspace. A feature flag may hide the dashboard after authentication. The user may appear logged in until the next API request returns an unexpected authorization error.

Users do not experience software as isolated functions, components or endpoints. They experience connected journeys.

End-to-end testing checks whether those journeys work when the different parts of the system are brought together.

That makes E2E testing valuable, but it also makes it relatively expensive. These tests usually involve more infrastructure, more data, more dependencies and more possible failure points than lower-level tests.

A sensible strategy therefore does not try to automate every detail through the user interface. The goal is to protect the journeys that matter most.

What does end-to-end testing mean?

End-to-end testing, often shortened to E2E testing, validates a complete workflow through an application from the user’s starting point to the expected final outcome.

For a web product, that may involve the browser, the user interface, frontend application logic, backend services, APIs, authentication, permissions, databases, stored state, email systems, notification systems, payment providers, identity providers or other connected services.

The exact boundaries depend on the product.

A true end-to-end payment test might begin when a customer adds an item to a basket and finish when the payment is recorded, the order is created and the confirmation is visible.

In another test, the real payment provider may be replaced with its sandbox environment because charging a live card during every CI run would be unsafe and impractical.

The important point is not that every external dependency must always be live. It is that the test validates a meaningful journey through the relevant layers of the product.

A simple end-to-end testing example

Consider a SaaS collaboration platform.

A new customer creates an account, receives a verification email, logs in, creates a project, invites a teammate, changes the teammate’s permissions, confirms that the teammate receives a notification, then signs in as the teammate and verifies the new access level.

This journey crosses several parts of the system: registration UI, account API, database records, email delivery, authentication, project creation, invitation handling, role and permission logic, notifications and workspace visibility.

Testing only the signup form would tell the team whether the form behaves correctly. Testing only the registration endpoint would tell them whether the backend accepts and processes the request. Testing only the email template would tell them whether the message looks correct.

None of those checks alone proves that the full journey works.

An E2E test can reveal that the account is created but the verification link contains the wrong environment URL. It can reveal that the invitation is accepted but the teammate is added to the wrong workspace. It can also reveal that the backend updates the permission correctly while the frontend continues showing actions the user should no longer be allowed to perform.

That is the main value of E2E testing: it checks what happens between the individual parts.

Why end-to-end testing matters

Lower-level tests are usually faster and easier to diagnose, but they operate within limited boundaries. End-to-end tests provide a different kind of confidence by checking whether the connected product behaves as expected.

Users care about completing a goal, not whether an internal method returned the right object.

A customer wants to register, pay, book, upload, invite, export or complete another meaningful action. E2E tests frame coverage around these outcomes.

E2E testing can also expose mismatched field names, missing headers, outdated contracts, incorrect permissions, state-management problems and assumptions that differ between frontend and backend teams.

It can reveal environment and configuration problems too. A feature may fail because an environment variable is missing, the wrong API URL is configured, a callback domain is not permitted, a queue worker is not running, an email provider uses the wrong template ID, feature flags differ between environments or database migrations were not applied correctly.

These problems may only appear in a deployed, connected environment.

It protects revenue-critical and trust-critical journeys

Some workflows carry much more business risk than others.

Examples include checkout and payment, account access, subscription management, transferring or withdrawing funds, booking confirmation, changing user permissions, submitting sensitive information or completing an important data export.

A failure in these areas can directly affect revenue, access, security or customer trust.

Focused E2E coverage can provide useful protection around them.

Once a journey becomes stable and important, automating it can also help detect future regressions. A working subscription upgrade flow might later break after a billing change, pricing-page redesign or authentication update. A repeatable E2E test can identify that the connected journey no longer works even when the changed component appears unrelated.

What can end-to-end testing catch?

E2E tests are particularly useful for defects that appear only after several layers or actions interact.

For example, login succeeds but the session expires when the customer enters checkout. The user interface permits an action that the API incorrectly rejects. The API returns correct data, but the frontend maps or formats it incorrectly. A payment succeeds, but the order remains pending. An order is created, but the confirmation email is not sent.

Other examples include role changes not updating visible permissions, successful file uploads not appearing in the next workflow step, staging integrations failing after production deployment, password reset links pointing to the wrong domain, subscription downgrades not changing the next invoice, booking time zones changing before confirmation or exports containing data from the wrong workspace.

These are often not isolated frontend bugs or backend bugs. They are product-flow failures that occur across boundaries.

E2E testing compared with other testing types

End-to-end testing should not replace unit, integration, API, smoke or regression testing. It answers a different question.

Unit tests check small pieces of logic in isolation. A unit test might check that a pricing function calculates a discount correctly or that a validation function rejects an invalid date. These tests are normally fast, focused and easy to diagnose.

Integration tests check whether several components or modules work together. They can provide meaningful behavioural confidence without the full cost of browser-driven E2E coverage.

API testing validates backend behaviour directly. It is well suited to checking request validation, authorization, business rules, status transitions, response structures, error handling, repeated requests, boundary values and data consistency.

Smoke testing checks whether a build is basically usable. A smoke suite might confirm that the application loads, authentication works, the main dashboard is accessible and one essential transaction can be completed.

Regression testing checks whether previously working behaviour still works after changes. Regression coverage may include unit, API, integration, component and E2E tests.

E2E testing checks the complete journey across the connected system. It provides broader confidence, but failures often contain less immediate information about which exact component caused the problem.

A balanced strategy uses each layer for the risks it handles best.

The testing pyramid and the cost of too many E2E tests

The testing pyramid is a model for thinking about the balance between different automated testing layers.

At the bottom are many fast, focused tests such as unit tests. In the middle are integration, component and service-level tests. At the top is a smaller number of broad tests that exercise large parts of the system, including E2E tests.

The exact shape should not be treated as a universal quota. A frontend-heavy application, microservice platform, embedded system and data-processing service may need different distributions.

The broader principle is more useful: use the lowest practical testing layer that can give the required confidence.

E2E tests are slower because they may need to start the application, authenticate a user, create data, navigate several pages, wait for network activity and clean up afterwards.

They also have more failure points. A single E2E journey may depend on the browser, frontend, backend services, database, queues, caches, test data, network connectivity, external providers and environment configuration.

A failure in any of those areas can fail the test, even when the product change being checked is correct.

E2E failures can be harder to diagnose

A unit test usually points toward a small piece of logic.

An E2E test may only report that the final page did not appear. The team then has to determine whether the problem came from the UI, API, authentication, data setup, environment or third-party service.

They also require maintenance. Selectors change. Pages are redesigned. Workflows evolve. Test accounts expire. Sandbox behaviour changes. New feature flags appear.

Even a well-written suite requires active ownership.

A small E2E smoke suite may provide valuable feedback on pull requests or merges. A large suite running on every commit can delay developers and consume significant infrastructure.

More E2E tests do not automatically create more confidence. They may simply create more execution time, maintenance and noise.

What makes a good E2E test candidate?

A good E2E candidate is usually business-critical, common enough to matter, risky when broken, stable enough to automate, repeated often and useful for release confidence.

Checkout, subscription activation, booking confirmation and permission-sensitive administrative actions are common examples because they affect revenue, access, trust or security.

A password recovery flow may not be used daily by every customer, but a broken version can lock users out of the product. That makes it a strong candidate even if it is not the most frequent journey.

Stable behaviour also matters. Automating a feature that changes every few days often creates constant rework. New or uncertain flows may benefit more from manual exploratory testing until their expected behaviour becomes clearer.

The result should help the team make a decision. A passing test of a core purchase journey is meaningful. A passing test confirming that a decorative tooltip appears contributes very little to release confidence.

What should usually not be tested end to end?

Not every requirement deserves a browser-driven E2E test.

Tiny presentation details such as font size, icon alignment, simple visibility rules and isolated component states are usually better suited to component, visual or accessibility testing.

Every validation rule should not usually become an E2E test either. A registration form may contain dozens of field combinations. A few representative E2E checks can confirm that validation is connected correctly, while detailed boundaries and business rules are better tested at the unit, component or API level.

Highly unstable features are also poor automation candidates. When the workflow and expected behaviour are still changing, automation can become a daily repair task.

E2E tests should normally observe user-visible behaviour or meaningful system outcomes. They should not become tightly coupled to internal methods, temporary DOM structures or database implementation details unless those are intentionally part of the test boundary.

Cross-browser coverage matters, but running every journey across every supported configuration can become expensive. A risk-based approach may run critical journeys across primary browsers while running broader regression coverage on one representative configuration.

Manual end-to-end testing

E2E testing is not automatically the same as automation.

A QA engineer can manually follow a full workflow using a production-like environment, realistic accounts and connected services.

Manual E2E testing is particularly useful when a feature is new, expected behaviour is still being refined, the flow requires human judgement, usability matters, unexpected paths need exploration or a release needs focused validation.

During a manual checkout test, an experienced tester may notice that the flow technically succeeds but provides poor feedback during payment processing. They may find that returning from a failed payment leaves the basket in an unclear state or that the success page does not explain what happens next.

An automated script may only confirm that the final confirmation appears.

Manual E2E work is therefore not merely a temporary substitute for automation. It provides observation, judgement and adaptability that scripts do not.

Automated end-to-end testing

Automated E2E tests use software to perform actions and verify outcomes repeatedly.

Common tools include Playwright, Cypress, Selenium and WebdriverIO.

Automated E2E suites can run during pull-request validation, after merging changes, against a deployed test environment, before a release, on a scheduled basis or after production deployment as a limited smoke check.

Automation is most valuable when the flow is stable, repeated and important enough to justify the ongoing maintenance.

Reliable automation also requires stable selectors, controlled data, isolated tests, predictable environments, clear assertions, useful failure evidence and realistic scope.

A recorded browser script is not automatically a maintainable E2E strategy.

Flaky E2E tests

A flaky test can pass and fail against the same application code without a meaningful product change.

A test suite is valuable only when its results are trusted. When failures frequently disappear after a rerun, teams begin to assume that red results are false alarms. Developers rerun pipelines instead of investigating. Real regressions may be dismissed as another unstable test.

Flakiness commonly comes from fixed timing assumptions, elements that are not ready, unstable selectors, network delays, asynchronous background work, shared test accounts, conflicting test data, tests that depend on previous tests, external services, inconsistent feature flags, insufficient environment resources, animations, transitions and race conditions.

Use selectors based on stable user-facing roles, labels or intentional test attributes rather than fragile DOM paths.

Each test should be able to run independently. It should not inherit cookies, storage, data or other state from another test.

Retries can help identify intermittent behaviour and keep evidence from the failed attempt. However, they should not become a way to hide instability.

A test that only passes after three attempts is still providing information that deserves investigation.

Test data and environment problems

E2E testing depends heavily on the condition of the environment in which it runs.

A good script cannot compensate for unpredictable data, inconsistent configuration or a test environment that regularly becomes unavailable.

The test should know what state it starts from. For example, the account has no active subscription, the workspace contains two members, the invoice is unpaid, the booking slot is available or the product has a known inventory level.

Without a known starting point, a failure may be caused by old test activity rather than a product defect.

One test should not create data required by another test. That creates cascading failures and makes it difficult to run a test by itself.

Teams may reset data through direct database setup, internal test APIs, fixtures, seed scripts, disposable accounts, temporary workspaces or cleanup hooks.

The setup mechanism should be fast but should not bypass the actual part of the journey the test intends to validate.

E2E testing and third-party systems

Payments, email providers, identity platforms, CRMs, messaging services and external APIs introduce difficult choices.

Testing against the real external system provides stronger integration confidence, but it also introduces availability outside the team’s control, rate limits, variable response times, financial cost, difficult cleanup, provider-side changes, restricted access and unpredictable data.

Teams normally need a combination of approaches.

Use the provider’s sandbox or test mode when its behaviour is close enough to the real service. This is common for payment providers, identity services and communication platforms.

Mocks and stubs are valuable when the external service is slow, expensive, difficult to configure or unreliable. They also make negative scenarios easier to reproduce.

However, a fully mocked test does not prove that the real integration contract still works.

For critical integrations, the team may keep a limited set of tests against the closest available real environment. The strongest strategy is rarely “mock everything” or “test everything live.” It is a deliberate mix based on risk.

End-to-end testing in CI/CD

E2E tests can support continuous integration and delivery, but placement matters.

A small set of critical journeys can run after the application is built and deployed to a temporary or shared environment. These might confirm that the application loads, a user can authenticate, the central dashboard is accessible and one core action succeeds.

Longer journeys, browser combinations and secondary workflows can run later in the pipeline, before a scheduled release or against a release candidate.

Tests involving external providers, complex data or many configurations can run overnight or at another suitable interval. Scheduled execution is useful only when failures are reviewed promptly.

A limited set of safe checks can also verify that the live application, infrastructure and integrations are reachable after deployment. Production checks should use controlled accounts, avoid destructive behaviour and respect security and privacy constraints.

Do not make every commit wait for everything. Unit, component, API and integration tests can normally provide earlier and more specific information. Large E2E suites should be placed where their broader confidence is worth the additional time.

E2E testing for SaaS products

SaaS products often contain account states and role relationships that make E2E testing particularly useful.

A SaaS flow may behave differently for account owners, administrators, members, guests, billing contacts or support users.

It is not enough to confirm that a role value changes in the database. The resulting navigation, actions, data access and restrictions must also be correct.

Multi-tenant products need special attention. Tests should confirm that users only see data from the correct organisation or workspace.

Billing and subscription flows can include trials, active subscriptions, failed payments, upgrades, downgrades, scheduled cancellations, expired accounts, grace periods and reactivation.

Testing only the successful first purchase leaves much of the subscription lifecycle uncovered.

The difficult part is frequently not writing the browser action. It is creating and maintaining realistic account states reliably.

E2E testing and product quality

A journey can pass technically and still be poor.

A customer may complete checkout but wait with no visible progress for several seconds. A form may submit successfully but clear all entered information after a recoverable error. A permission change may work but provide no explanation to the affected user.

These are product-quality issues even when the final assertion passes.

E2E testing should therefore consider more than whether the system eventually reaches the expected page.

QA should also observe whether the journey is understandable, whether progress is visible, whether errors explain what happened, whether users can recover, whether the next step is clear, whether important state changes are communicated, whether response times feel reasonable and whether behaviour is consistent across the flow.

Automation can confirm known expectations. Manual and exploratory QA are still needed to question whether those expectations create a good product experience.

How to plan an E2E testing strategy

A practical E2E strategy can be built in stages.

Start by identifying the most important user journeys. Focus on outcomes rather than pages. Examples include creating an account and reaching the first useful product state, completing a purchase, inviting and managing a teammate, upgrading a subscription, submitting an application or creating and confirming a booking.

Then rank the journeys by risk. Consider business impact, user frequency, financial consequences, security and permission concerns, history of defects, integration complexity, difficulty of manual checking and likelihood of change.

Manual E2E testing should usually come before automation. It helps the team understand the real flow, clarify expected behaviour and discover unstable areas before encoding assumptions into scripts.

Automate stable, repeatable journeys that are important and mature enough to justify maintenance.

Keep detailed rules at lower layers. Use unit tests for isolated logic, API tests for backend rules and integration or component tests for combinations that do not require the whole deployed system.

Test data, isolation, suite placement and failure evidence are also part of the strategy, not afterthoughts.

Common end-to-end testing mistakes

One common mistake is automating too many flows. The team turns every manual test case into a browser script, and the result becomes slow, expensive and difficult to trust.

Another mistake is treating E2E as the only quality layer. Broad tests cannot provide the speed, precision and depth of a balanced unit, API, component and integration strategy.

Some teams ignore API testing and try to validate every backend rule through the UI. That makes failures slower to diagnose and edge cases harder to cover.

Testing only the happy path is another risk. Critical journeys also need selected recovery and failure coverage, such as declined payment, expired invitation, insufficient permission or interrupted upload.

Other common mistakes include using unstable selectors, making tests depend on one another, leaving flaky tests in the suite, using retries as the fix, failing to review tests after product changes, running a huge suite too often and confusing coverage with confidence.

A large number of tests does not prove that the product’s main risks are protected. The important questions are which user outcomes are covered, which risks are still exposed, whether failures are trustworthy and whether the result helps the team make a release decision.

A practical E2E coverage example

For a subscription-based SaaS product, a balanced approach might look like this.

Unit and service-level coverage checks pricing calculations, billing dates, status transitions and permission rules.

API tests check subscription creation, upgrades, downgrades, invalid requests, authorization and provider callback handling.

Component and integration tests check the pricing interface, confirmation states, error messages and frontend handling of different subscription responses.

E2E smoke coverage checks that a user can register, start a trial and reach the product.

Focused E2E regression coverage checks that an account owner can upgrade a subscription, see the updated plan and receive confirmation.

Manual exploratory coverage examines failed payments, unclear recovery states, switching plans repeatedly, browser navigation and unusual account conditions.

This provides much stronger information than trying to automate every billing variation through the browser.

Conclusion

End-to-end testing is valuable because users experience the connected product, not its components in isolation.

A login function, authentication endpoint and dashboard component may all pass their individual tests while the real journey remains broken. E2E testing helps expose those gaps by validating meaningful workflows across the frontend, backend, APIs, data, authentication and connected services.

But it should not be treated as a way to test everything through the user interface.

Large E2E suites can become slow, fragile and expensive. They can delay CI/CD, depend on unstable environments and create failures that are difficult to diagnose. When flakiness becomes normal, the suite can lose the trust it was meant to provide.

A stronger strategy focuses E2E testing on critical user journeys, business risk and stable product flows. It combines those tests with focused unit, API, component and integration coverage. It also treats test data, environments, third-party systems and maintenance as part of the strategy.

The goal is not to build the biggest E2E suite.

The goal is to maintain a focused and reliable set of tests that gives the team useful confidence before users are affected.

Need practical QA support?

Laidoner Solutions helps software teams with manual QA, API testing, localization review, release checks and clear defect reporting.

Contact Us