End-to-end tests with Playwright
An end-to-end test drives the real web shop in a real browser, the way a customer would. A few of them, aimed at the journeys that make money, catch what no unit test can. Written badly, they become the slow, flaky tests nobody trusts. This lesson shows how to write the good kind with Playwright Test.
By the end you can
- Choose the handful of checkout journeys that deserve an end-to-end test
- Find elements with role, label and test id locators that survive a redesign
- Wait with auto-waiting and web-first assertions, and never with a fixed sleep
- Log in once with
storageState, seed data through the API, and wrap screens in page objects that last - Mock the payment provider with
page.route, and debug a failure from its trace
The everyday picture
Mangrove sends a mystery shopper into a store once a month. A good mystery shopper does three things well. She finds the cooking oil by reading the shelf labels, never by remembering "third shelf from the door", because the shelves get moved. At the till she waits until the cashier is ready, however long that takes, instead of counting to five and walking off. And she arrives with a loyalty card already set up and a basket already planned, so her visit is spent on the part she is there to check: paying.
A good end-to-end test is that shopper. It finds buttons by what the customer sees, waits for the page to be ready instead of sleeping, and starts each test already logged in with the cart already filled, so the browser time goes on the journey under test.
What end-to-end tests are for, and how Playwright runs them
An end-to-end (E2E) test is the most expensive test you own. Each one takes seconds instead of milliseconds, needs a full environment, and can fail for reasons far from the code that changed. So you keep them for the few journeys where a break costs real money, and you push every other check down to a cheaper level, as A test strategy, not a pile of scripts explains. For Mangrove's web shop, the browser version of the customer app, that list is short: sign in, add to cart and check out by card, by mobile wallet and by cash on delivery, and track the order. That is five to eight tests. The price rules (the 150 cent delivery fee under $25, FRESH10, the staff discount) are tested in milliseconds by the unit tests from Unit and API tests. The E2E test only proves the screens, the API and the database are wired together.
Playwright Test (@playwright/test, version 1.64 at the time of writing) runs these tests in Chromium, Firefox and WebKit. Its model has three layers. A browser is one running browser process. A browser context is like a brand-new incognito profile: its own cookies, its own local storage, nothing shared. A page is one tab inside a context. Playwright gives every test its own new context, which takes milliseconds, so a test that logs out or fills a form can never leak into the next one. Tests run in parallel in several worker processes, each with its own browser.
Isolation in the browser does not isolate the server. If two parallel tests log in as the same test customer, they share one cart on the order service, and one test's rice lands in the other test's checkout. The fix is one test account per worker, which you build in Build it.
Quick check
Which of these deserves an end-to-end test in the checkout suite?
The wallet journey crosses the screens, the payment step, the order service and the tracking page, and a break there stops sales. The discount clash is a pure rule, checked by a unit test in a millisecond. The 422 is an API contract, checked by an API test without a browser.