Skip to main content
Insyrge - Zoho CRM & Business Automation Consulting
← Back to All ArticlesAI & Business Automation

End-to-End Testing for Business Web Apps

How to choose which user journeys to cover with end-to-end testing, keep browser tests stable and run them on every release.

•Manav Sharma
End-to-End Testing for Business Web Apps

Plan end-to-end testing for business web apps: pick the journeys that matter, use resilient locators, isolate test data and run tests in CI on each change.

Every release of a business web application carries a small risk that something users depend on stops working: a login form that no longer submits, a checkout step that hangs or an invoice page that shows the wrong totals. Unit tests catch many problems inside individual functions, but they cannot tell you whether the whole journey still works in a real browser. End-to-end testing fills that gap by driving the application the way a person would, from the first page to the final confirmation, and checking the results along the way. This guide explains how to decide what to cover, how to keep browser tests stable and how to fit them into your release process without slowing the team down.

What end-to-end testing covers

An end-to-end test exercises the application through its user interface and the services behind it. A typical test opens a browser, signs in, fills in a form, submits it and checks that the right message appears and the right data was saved. Because it passes through the front end, the API, the database and any connected services, a single test can reveal problems that no isolated test would find, such as a renamed field that breaks a form submission or a configuration change that blocks a payment step.

That breadth is also the main cost. End-to-end tests are slower than unit tests, depend on more moving parts and can fail for reasons unrelated to the change being tested. A sensible test strategy uses many fast unit tests, a solid layer of API and integration tests, and a smaller set of end-to-end tests focused on the journeys that matter most. Our guide to API contract testing covers the integration layer that sits below browser tests.

Choose the journeys that matter

Start with a short list of user journeys where a failure would hurt the business or its customers. For most business applications these include:

  • Signing up, signing in and resetting a password
  • Creating and editing the core record, such as an order, a booking or a support request
  • Paying, approving or submitting something that triggers money or commitments
  • Viewing key documents such as invoices, statements or contracts
  • Permission boundaries, such as a standard user being unable to reach admin pages

For each journey, write down the steps and the expected result in plain language before writing any code. This keeps the tests tied to real behaviour rather than to how the page happens to be built today.

Pick a tool that suits the team

Several frameworks can drive browsers for end-to-end testing. Playwright Test describes itself as an end-to-end test framework for modern web apps that bundles a test runner, assertions, isolation, parallelization and tooling, and supports Chromium, WebKit and Firefox on Windows, Linux and macOS (Playwright: Installation). Other teams use Selenium or Cypress. The choice matters less than the habits around it: stable locators, isolated data and fast feedback. Choose a tool your developers will actually maintain, in a language they already use. The same libraries also power browser automation beyond testing; our guide to Playwright web scraping shows Playwright used for data collection, with many of the same locator and waiting habits.

Write tests that survive design changes

Fragile tests are the main reason teams abandon browser testing. A test that breaks every time someone changes a CSS class or moves a button soon gets ignored. To keep tests stable:

  • Locate elements the way users find them, by role, label or visible text, rather than by long CSS paths
  • Add dedicated test IDs for elements that have no stable label
  • Assert on outcomes users care about, such as a confirmation message or a saved value, not on page structure
  • Avoid fixed sleeps; rely on the framework to wait for elements to be ready and for expected text to appear
  • Keep each test focused on one journey so a failure points to one cause

When a test does break after a deliberate design change, update it in the same pull request as the change. Treat test code with the same care as application code.

Isolate test data

Tests that share data interfere with each other. One test deletes a record another test expects, or two tests run at the same time and change the same account. Give each test its own data wherever possible:

  • Create the records a test needs at the start, through an API or a seed script, rather than relying on data left by earlier runs
  • Use unique names or IDs per run so parallel tests do not collide
  • Clean up after tests, or run against an environment that is reset regularly
  • Never run destructive tests against production data

Test accounts and credentials should be separate from real user accounts and stored as secrets in the CI system, not in the repository.

Worked example: a hypothetical coverage plan

The table below is a hypothetical plan for a small customer portal. It shows how to prioritise journeys and decide where each check belongs, not a recommended test suite for any particular product.

JourneyRisk if brokenTest layerRun whenSign in and sign outUsers locked outEnd-to-endEvery changeSubmit a support requestRequests lostEnd-to-endEvery changeDownload an invoice PDFBilling complaintsEnd-to-endEvery changeInvoice total calculationWrong amountsUnit testsEvery changeRequest data saved to CRMData gapsAPI or integration testEvery changeProfile photo uploadMinor annoyanceEnd-to-endNightlyAdmin page blocked for standard usersData exposureEnd-to-endEvery change

The pattern is simple: put business rules in fast tests, and use browser tests to confirm that the main journeys hang together.

Run tests on every change

End-to-end tests deliver most of their value when they run automatically. Run the core set on every pull request or merge to the main branch, and the wider set on a schedule. Run against a dedicated test environment that resembles production in configuration, with test integrations or sandboxes for third-party services such as payment providers.

Keep the feedback fast. Run tests in parallel where the framework supports it, keep the core suite small and move slower or lower-risk tests to a nightly run. A suite that takes too long to finish encourages people to merge without waiting for the result.

Deal with flaky tests honestly

A flaky test passes and fails without any change to the code. Retries can hide occasional noise: the Playwright documentation describes test retries as a way to re-run a failed test automatically, which is useful when a test is flaky and fails intermittently (Playwright: Retries). Retries should not become a permanent cover for real problems, though. Track which tests needed a retry, investigate the repeat offenders and fix the cause, whether it is a timing assumption, shared data or a slow dependency.

When a test fails, make the failure easy to understand. Save screenshots, logs and traces from failed runs so the person investigating does not have to reproduce the problem by hand.

Keep the suite healthy over time

A test suite needs ownership. Review it regularly: remove tests for features that no longer exist, merge tests that check the same thing and add tests when incidents reveal a gap. When a bug reaches production, ask whether an end-to-end test would have caught it, and add one if the journey is important enough.

Frequently Asked Questions

What is end-to-end testing?

It is testing a complete user journey through the real interface and the services behind it, such as signing in, submitting a form and checking that the right result appears and is saved.

How many end-to-end tests should we write?

Cover the journeys where a failure would hurt the business most, and keep detailed business rules in faster unit and API tests. A small, reliable suite is more useful than a large one that is often red.

Why do browser tests become flaky?

Common causes include fixed waits, fragile locators, shared test data and slow or unreliable dependencies. Fixing these usually works better than adding retries.

Should end-to-end tests run against production?

Not destructive ones. Run the main suite against a dedicated test environment and keep any production checks read-only and limited.

Build tests your team will keep

We help teams choose which journeys to cover, write stable browser tests and run them in CI alongside the application. See our custom app development services, or talk to us about end-to-end testing.

About the Author

Manav Sharma is the founder of Insyrge and a CRM solutions architect. He works across Zoho, Salesforce, HubSpot, Odoo and more, designing the CRM setups, integrations and automations that keep sales and operations teams working from the same data.

Need Help Implementing This in Your Business?

Our certified Zoho consultants and automation experts can help you design and deploy custom workflows tailored to your operations.

Book Free Consultation