E2E Test Development with Selenium WebDriver for Websites

Manual checks can no longer keep up with frequent website updates, and regressions slip into production. We develop and implement turnkey E2E tests with Selenium — from scenarios to a launch protocol. This reduces regression time many times over and takes routine work off your team's plate.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Frequently Asked Questions

Why manual website testing stops catching regressions

Manual regression testing predictably hits a ceiling when the number of scenarios grows faster than the team.

For a release where a single payment form changed, you have to run through the entire catalog, cart, account area, and checkout — and the tester physically walks the same paths for as long as attention holds.

By the third hour of repetitive runs, edge cases get missed: an empty promo code, an item going out of stock between being added to the cart and payment, a repeated form submission on a double click.

The cost of such a mistake is a defect that isn't found in prod. The regression surfaces with customers, and the investigation takes longer than the run itself would have, because reproduction depends on the exact sequence of steps, the cart state, and the user's data.

The more frequent the releases, the shorter the window between rollout and detection — and the more expensive each missed breakage.

Selenium E2E testing addresses exactly this bottleneck: a scenario is described once in code and then runs identically on every release, without fatigue or variability.

Automated tests walk the full user journey — from opening the page to confirming the order — in a real browser, with real navigation and state checks after each step.

The run goes in parallel across multiple browsers and resolutions, so regressions are caught before rollout, not after.

The key difference from a manual run is reproducibility. A test either passes or fails with a specific step, screenshot, and log, and that result doesn't depend on who ran the check or what mood they were in.

Let's break down how such a pipeline is built and what it takes to keep it from turning into a fragile set of failing checks.

What end-to-end browser testing delivers

An end-to-end scenario walks the entire user journey — from opening the page to confirming an order in the customer account.

It catches what unit tests miss: frontend and API desync, a lost session after a redirect, an incorrect payment gateway response, broken layout at an intermediate step.

These are exactly the defects that reach the customer and cost the most — checkout being down for a few hours is more noticeable than any internal error.

Selenium WebDriver drives a real browser the same way a human does: clicks, enters data, waits for the server response. Running a suite of 40-60 key scenarios takes 10-15 minutes in parallel threads — that fits into every commit rather than a nightly run.

The share of defects caught before release grows from 60-70% to 90%+: the critical paths of payment, registration, and authorization are covered by checks continuously, not just before deployment.

Release stability rests on the robustness of the tests themselves. We build locators on data attributes rather than chains of classes, isolate test data, and remove dependency on run order — the suite stops "flaking" and people start trusting it.

We maintain reporting separately: every failure shows the step, a screenshot, and the server response, so triage takes minutes instead of hours of digging through logs.

The class of failures that goes away along with this is regression in adjacent areas. A change in the cart breaks checkout, a library update breaks dropdowns — end-to-end checks surface this on the build, not on release day.

Run time and scenario coverage become measurable: you can see how many paths are covered and how many minutes the pre-deployment check takes.

Comparison of approaches to UI test automation

The choice of tool determines not the speed of writing the first checks, but how long they will live without being rewritten.

A code framework, a low-code builder, and a cloud service solve the same task in different ways, and switching between them almost always means redoing the suite from scratch — which is why the decision is made before the start, not along the way.

Option When it fits Limitations
Code framework Complex scenarios, authorization, integrations, dynamic forms; checks in a shared repository alongside the product Requires experienced engineers; longer time to the first stable checks
Low-code builder Typical user paths, frequent business-driven edits, quick coverage of key pages Handles non-standard logic and complex expectations poorly; hits a ceiling as scenarios grow
Cloud service Need to run across many environments and browsers without your own infrastructure Dependence on an external platform, restrictions on access to internal staging environments, payment based on run volume

What matters in practice

A code framework gives full control over expectations and synchronization, but requires discipline: without a Page Object layer and explicit waits, checks start failing out of nowhere.

Low-code wins at the start — the first scenarios come together in days — but as logic grows more complex, some steps still end up in code. A cloud service removes the infrastructure question, but adds restrictions on access and environment predictability.

Our experience: most often the working setup is a code framework for critical paths and low-code for quickly covering secondary pages. Such a hybrid provides coverage without growing maintenance time. We analyze your scenarios and select the option that fits them.

How we implement E2E testing with Selenium

We start implementation with a scenario audit: we break down the user paths that bring in money and break most often — checkout, payment, registration, account area.

For each one we record the expected result and failure points, and cut duplicates and paths that are more reliably covered by unit tests. The output is a priority map: what we cover first and what we consciously defer.

Next we build the test scheme and environment. We set up an isolated stand with test data, prepare browser images and drivers, and configure parallel execution so a run doesn't stretch on for hours.

We write tests on Selenium WebDriver with explicit waits instead of pauses — that way checks don't "flicker" on a slow network.

  1. Scenario audit — inventory of paths, priorities, pass criteria.
  2. Coverage scheme — which checks go in E2E, which move down a level, dependency map.
  3. Environment setup — test stand, data, browsers, parallel execution.
  4. Writing and running — tests on Selenium WebDriver, debugging to a stable green run.
  5. Stability check — running in series, catching flaky checks, isolating data between tests.
  6. Handover — running in the shared build pipeline, reports, instructions for the team.

For us, stability is not a one-off green run but repeatability: we run the suite in series and weed out checks that fail not because of a defect but because of a data race or timing.

Each test gets its own data and doesn't depend on its neighbors, so a failure points to a real problem rather than to the run order.

We hand over not just the code but a working loop: tests run in the shared build pipeline on every change, and the report shows which path failed and at which step. The team sees regressions before deployment, not after user complaints.

Artifacts: configurations, reports, and run procedures

What you get at the end is not a "folder with tests" but a kit that the client's team can use to run, read, and evolve the checks without us.

Each artifact addresses its own class of questions: configurations — "how to reproduce the environment," reports — "what exactly failed," procedures — "who runs it and when."

  • Environment configurations — profiles for local runs, the acceptance staging environment, and pre-production, with externalized addresses, credentials, and test data sets; secrets are not stored in the repository but injected from a vault.
  • Scenario map — a coverage map: which user paths are covered by end-to-end checks, where manual steps remain and why; it shows exactly what is verified on each run.
  • Access and role policies — which accounts the tests need, what permissions they are granted, and how they are isolated from production data so that a run does not affect real users.
  • Run reports — the result for each scenario with the step at which the failure occurred, a screenshot of the page state, and an attached log; a failure can be analyzed without manually reproducing it.
  • Run procedure — when the checks run automatically (on every commit and before deployment), when they run on a schedule, who reviews the result, and within what timeframe they respond to a red run.
  • Maintenance guide — how to add a new scenario, update a selector after a markup change, and where to look if a test starts failing with no code changes.
  • Flaky check log — a list of scenarios that periodically fail for external reasons, with the cause noted and a decision: fix, isolate, or remove.

We hand over the kit with a walkthrough: we show how to run a test run on your staging environment, where to view the report, and what to do when something fails.

After that, the client's team maintains the checks on their own — or we stay on for support under an agreed procedure.

Case study: how regression time was cut on a large portal

A portal with a personal account, catalog, and request submission lived on manual regression: three engineers spent two working days on a full pre-release run, and some checks were performed "from memory" by the end of the cycle.

At the same time, defects accumulated that were caught only in production — most often in the "authorization → cart → payment" chains, where the manual scenario is expensive to reproduce again.

We broke down the critical user paths and converted them into E2E tests on Selenium WebDriver: authorization and access recovery, catalog search and filters, request submission, personal account, integration with the payment gateway on the test environment.

Tests run in containers in isolated environments, data is prepared and rolled back before each scenario — the run does not depend on the state of the previous one.

What changed in the metrics

Metric Before After
Full regression 2 working days 40 minutes
Share of defects caught before release ~60% 92%
Unstable builds due to tests — less than 3% of runs
Manual checks per release all only new scenarios

Stability was achieved not by "framework magic" but by discipline: explicit waits instead of fixed pauses, stable locators, a separate data preparation layer, and automatic rerun only for scenarios with external dependencies.

Each nightly run is compiled into a report with the step at which the test failed, a screenshot, and a log — analysis takes minutes, not half a day.

Two months after implementation, the team stopped fearing Friday releases: regression runs on schedule, and engineers work on new scenarios and analysis of real defects instead of repeating the same clicks.

How does an E2E test differ from integration and unit tests?

A unit test verifies a single isolated unit of logic: a discount calculation function, a field validator, a format conversion.

All external dependencies — database, network, payment gateway — are replaced with stubs, so such a test runs in milliseconds and pinpoints exactly where something broke.

An integration test goes one step higher: it verifies the junction of two or three components — that a service correctly writes to the database, that the orders module actually calls the payment module, that a queue delivers a message to the right handler. It catches contract and format errors that unit checks cannot see by definition.

An E2E test is an end-to-end scenario from the perspective of a real user: open the site, log in, fill a cart, place an order, see confirmation. There are no stubs here — a real browser, a real backend, a real database are all running.

That is precisely why end-to-end verification answers the main business question: "does the product work as a whole," rather than "does an individual function work."

The testing pyramid arranges these levels by the ratio of cost to value. At the base are hundreds of unit checks: cheap, fast, run on every change. The middle is dozens of integration tests: more expensive, but they cover the junctions.

The top is a handful of E2E scenarios for critical user paths: placing an order, registration, payment. The pyramid must not be inverted: if you build checks only on end-to-end scenarios, the run stretches out, failures are flaky, and the cause of a breakdown is not obvious.

In practice, the boundary blurs: an integration test with a real database and a running frontend is already almost E2E. We label the levels by what exactly is replaced with a stub — this gives an unambiguous criterion and a predictable cost of maintaining the set of checks.

Common technical concerns before starting

Before starting, engineers usually ask the same set of questions — and these are the right questions.

E2E testing with Selenium WebDriver breaks not when writing scenarios, but when operating them: selectors change along with the markup, environments diverge, test data conflicts between runs. Below is how we address each of these points.

Won't the tests become fragile in a month?

Fragility is a consequence of coupling to the markup. We move locators into a separate layer, use stable attributes instead of chains of classes, and add explicit condition waits instead of fixed pauses. A test that fails because of a renamed button is fixed in one place, not in forty scenarios.

Who maintains the suite after handover?

Maintainability is built into the structure: pages are described by objects, steps by reusable actions, and reporting shows exactly which step failed and on which screenshot.

This reduces the cost of a fix to minutes and allows your team to run the suite independently, without us.

How do the tests behave across different environments?

We move addresses, credentials, and browser parameters into configuration rather than code. The same suite runs on the development stand, pre-production, and production without changes — only the run profile changes.

What about test data?

Each run prepares its own data and cleans up after itself, so tests don't depend on execution order and don't conflict during parallel execution. Where data is needed from external systems, we set up stubs — the suite stops depending on someone else's availability.

How will this integrate into our build pipeline?

The suite runs on a schedule and on every change, the report arrives in the team's usual channel, and a failure blocks the release.

Rolling back is simply disabling a step: the tests don't touch the application code and don't interfere with the release if they're temporarily removed.

Describe your task — we'll come back with an estimate and a plan: which scenarios we cover first, how we organize the data, and what will be needed from your infrastructure.

Let's discuss your task and come back with a plan

To come back with an estimate and a plan, rather than generalities, we need to understand your setup: which scenarios are critical, where the tests live, who runs them and how often.

E2E testing with Selenium WebDriver doesn't break down at "writing tests" — it breaks down at the environment and maintenance — so we first clarify the inputs, then calculate.

What we clarify in the first conversation:

  • which user paths we cover first — payment, registration, personal account, checkout;
  • which environment we run on — a separate test setup or a production-like environment with test data;
  • how the tests fit into your process — manual runs, a nightly build, or a check before a release rollout;
  • which browsers and resolutions are a priority for your audience;
  • who on the client side accepts the result and triages failed runs;
  • whether there is access to test accounts, payment sandboxes, and APIs that the test calls directly.

Based on these answers, we form a work plan: a scenario map, the framework structure, a set of stable locators, run reporting, and a support policy.

The estimate is based on the number of scenarios and their complexity, not "for the whole project" — that way you see what you're paying for and what can be added later.

We break the timeline into stages: the first working set of tests for critical paths, then expanding coverage.

Describe the task in your own words — what the product is, which scenarios are painful to check manually, what stack and environments you have. We'll come back with an estimate, a work plan, and timelines by stage.

Our competencies:

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1393
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1368
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1139
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1152
  • Website development for SBH Partners
    Website development for SBH Partners
    1231
  • Website development for Red Pear
    Website development for Red Pear
    641