SAll projects
fr
All projects

Test automation · End-to-end QA

Carpooling Test Automation

A test strategy and end-to-end suite over a carpooling web application, from requirements to anomaly tracking.

A full QA activity over a carpooling web application: requirements analysis into a test strategy, test plans and data sets, an end-to-end Selenium framework built on page objects and explicit synchronisation, a Postman layer over the REST API, regression runs in GitLab CI, and anomaly tracking in Jira.

0functional areas covered
UI + APItest layers
POMtest architecture

Problem

The value of a carpooling app lives in journeys that cross several features at once: a passenger joins a trip, the driver confirms, the trip completes, and only then does a debt appear between two people. Unit tests on either side of the API cannot reach that. End-to-end tests can, but they are also the first suite a team deletes, because they break on every markup change and fail intermittently on asynchronous updates.

Objectives

  • Derive the test strategy from the requirements and functional specifications, so coverage is decided by what the product promised rather than by what the code happens to expose.
  • Prove the journeys that matter end to end, rather than the units on either side of the API.
  • Cover the areas where a regression is visible to a user: authentication, vehicles, trips, friends and debts.
  • Make the suite maintainable enough to survive UI change instead of being deleted after the first redesign.
  • Make it reliable enough to be trusted in CI, because a suite that fails intermittently stops being read.

Implementation

  • Started from the requirements and functional analysis: a test strategy naming what must be covered and to what depth, then test plans, test cases and the data sets each case runs with — written before the automation, so the automation has a specification to satisfy.
  • Page Object Model: each screen owns its selectors and exposes methods in the language of user intent, so a test reads as a journey and a markup change is fixed in one file.
  • Reusable components for the elements that recur across screens, so shared UI is modelled once instead of re-described in every page object.
  • Explicit waits bound to the specific condition each step depends on. A single-page app updates asynchronously; fixed sleeps are simultaneously too long for a fast machine and too short for a slow one, which costs both time and trust.
  • Data-driven cases: one journey definition exercised across multiple inputs, separating what is being tested from what it is tested with, so adding a case is adding data rather than code.
  • Assertions made on what the interface presents after an action rather than on internal state, because that is the thing a user would notice breaking.
  • A Postman collection covers the REST API as a separate layer, so a broken contract is caught without going through the interface and a UI failure can be attributed to the frontend or the backend rather than guessed at.
  • Functional and regression runs execute in GitLab CI, and results, anomalies and test campaigns are recorded in Jira so a defect has a trail from the failing case to its fix.

Architecture

Test strategy

Requirements
  • requirements analysis
  • functional specifications
Plans
  • test plans
  • test cases
  • data sets

Test framework

Driver
  • Selenium WebDriver
  • browser session
Pages
  • Page Object Model
  • reusable components
Synchronisation
  • explicit waits
  • UI-level assertions
Cases
  • pytest fixtures
  • data-driven cases

Suites

Coverage
  • authentication
  • vehicles
  • trips
  • friends
  • debts
  • key journeys
API
  • Postman REST collections

Continuous integration

Pipeline
  • GitLab CI
  • functional + regression runs
Tracking
  • Jira: anomalies & test campaigns

Technologies

  • Selenium
  • WebDriver
  • Python
  • Pytest
  • Page Object Model
  • Postman
  • GitLab CI
  • Jira
Demo video coming soon

Challenges & solutions

Challenge

End-to-end suites are usually abandoned, not because they find nothing but because every UI change breaks dozens of tests at once.

Solution

Confine selector knowledge to page objects. The cost of a redesign then scales with the number of screens changed, not with the number of tests that touched them.

Challenge

Asynchronous UI updates make naive tests fail intermittently, and an intermittently failing suite is quickly ignored, which is worse than having no suite at all.

Solution

Wait on conditions, never on the clock. Each step blocks until the state it needs is actually present, which is both faster than a conservative sleep and more reliable than an optimistic one.

Challenge

The debt logic is where a bug costs the most, since it concerns money between people, and it only becomes observable after a multi-step journey.

Solution

Exercise it as a journey across screens rather than as an isolated check, so the assertion lands on the state a user would actually see and dispute.

Challenge

A suite that repeats the same flow for every input becomes unmaintainable long before it becomes complete.

Solution

Drive cases from data, so coverage grows by adding rows rather than by copying test functions.

Challenge

A failing end-to-end test proves something is broken but not where, and chasing a UI symptom into the backend is the slowest way to find out.

Solution

Test the REST API separately with Postman. If the API layer passes and the UI fails, the fault is in the frontend; if both fail, it is not. The second layer pays for itself in diagnosis time.

Results

  • The test cases trace back to the requirements rather than to the implementation, so the suite says what the application was supposed to do instead of restating what it currently does.
  • Two layers rather than one: Postman exercises the REST API directly, which localises a contract break to the backend in seconds, while the Selenium suite proves the journey a user actually takes.
  • Six functional areas are exercised through the real interface, including the money paths where a regression is most expensive.
  • Selector knowledge lives in the page classes, so a renamed element is a one-line change rather than a sweep across the suite.
  • Waiting on conditions rather than on the clock removes the intermittent failures that make a suite get ignored, which is what decides whether it is allowed to gate a merge.

Lessons learned

  • Writing the test plan before the automation changes what gets automated. Starting from the requirements surfaced cases that would never have occurred to me reading the code, because the code cannot tell you what it was supposed to do.
  • A test suite's real enemy is maintenance cost, not missing coverage. The indirection of the Page Object Model is worth paying for precisely because it decides whether the suite survives the next redesign.
  • Explicit waits are not a style preference. Sleeps trade speed against reliability and lose on both, and reliability is what earns a suite the right to block a merge.
  • End-to-end tests justify their cost on the paths that cross several features at once — which is exactly where unit tests on either side of the API cannot see.