Skip to content

Chapter 1 · E2E Testing and Playwright Overview ​

Chapter goals: Understand where E2E testing sits in the test pyramid, clarify Playwright's architectural advantages over Selenium, install Playwright, and get the environment running.

1.1 E2E in the Test Pyramid ​

The classic test pyramid is divided into three layers from bottom to top:

LayerQuantitySpeedStabilityWhat It Verifies
Unit TestsMostMillisecondsVery stableFunction/class logic
Integration TestsModerateSecondsFairly stableModule collaboration, databases, APIs
E2E TestsFewestTens of secondsFragileComplete user journeys in a real browser

E2E (End-to-End) testing simulates the full process of "a real user opens a browser → interacts with the page → sees the result." It's slow and expensive, but it's the only thing that answers one question: does it actually work when users use it? So the principle for production practice is "few but precise" — only cover critical paths (login, checkout, payment), not every branch.

Positioning of this course

The pytest course on this site covers the lower half of the pyramid; this course focuses on the top layer. Both courses share the same pytest knowledge system — from Chapter 6 onward you'll reuse fixture skills extensively.

1.2 Selenium WebDriver vs Playwright: Architecture Determines Experience ​

The older Selenium WebDriver approach works by "external remote control":

text
test code → HTTP request → WebDriver driver process → browser extension injects JS → page

Every operation requires cross-process communication, and the driver has no idea when the page has finished rendering — you can only patch it with manual time.sleep(3) or explicit waits. This is the root cause of flaky tests in the Selenium era.

Playwright does things completely differently: the test process talks to the browser through a direct protocol pipe (Chromium uses CDP, Firefox/WebKit use patched kernel-inbuilt protocols):

text
test code ←persistent connection→ browser kernel
           (event-driven, bidirectional push)

This brings three qualitative improvements:

  • Fast: no intermediate driver layer; operations go directly to the kernel;
  • Auto-wait: the kernel knows the page's real state; Playwright auto-blocks until an element is "visible, stable, and actionable";
  • Event reliability: click fires a real input event, not a synthesized JS event; you can also listen to network, console, and other kernel-level signals.

1.3 Three Browser Engines ​

Playwright supports all modern rendering engines:

  • Chromium — the engine behind Chrome/Edge, the daily default;
  • Firefox — a patched version precisely driven by the automation protocol;
  • WebKit — Safari's engine, letting you test Safari behavior on Linux/Windows.

One API across three engines means you can cover Safari compatibility from a Linux CI without needing a Mac farm.

1.4 Sync and Async Dual APIs ​

Playwright Python provides both sync_api and async_api mirror APIs:

python
# Sync style: intuitive, great for scripts and most tests
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()
python
# Async style: ideal for asyncio apps and high-concurrency scraping/load-testing
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto("https://example.com")
        print(await page.title())
        await browser.close()

asyncio.run(main())

Both APIs are fully equivalent; the async version just adds await to every method. The first half of this course focuses on sync; Chapter 18 covers async in depth.

1.5 Installation and Environment Verification ​

bash
# Install the library
pip install playwright

# Download all three engines (one-time, ~hundreds of MB)
playwright install

# Optional: install system deps (often needed on Linux)
playwright install-deps

Verify the install:

bash
playwright --version
# Version 1.62.x

Then run a minimal smoke script smoke.py:

python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://example.com")
    assert "Example Domain" in page.title(), "Title mismatch"
    print("✅ Environment OK, title:", page.title())
    browser.close()
bash
python smoke.py
# ✅ Environment OK, title: Example Domain

Version pinning

The playwright pip package and browser engines are tightly coupled: after upgrading the pip package, you must re-run playwright install to download the matching engine versions, or you'll get "executable not found" errors.

1.6 Chapter Summary ​

  • E2E sits at the top of the test pyramid: few but precise, only test critical user paths;
  • Playwright connects directly to the browser kernel protocol — faster, auto-waits, more realistic events than Selenium;
  • One API covers Chromium / Firefox / WebKit;
  • Both sync_api and async_api are fully equivalent;
  • Remember to re-run playwright install after upgrading the Playwright package.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What is the most fundamental architectural difference between Playwright and Selenium WebDriver?

2. To verify Safari compatibility on a Linux CI, which engine should you use?

3. After upgrading the playwright pip package you get "browser executable not found". Why?

4. Which statement about sync_api and async_api is correct?

🛠️ Hands-On Exercises ​

  1. Write a script using the sync API that visits example.com and playwright.dev in sequence, printing each <title>.
  2. Rewrite exercise 1 in async style; compare the two approaches.
  3. Run your script with both headless=True and headless=False; observe the difference. Add slow_mo=1000 to feel the slow-motion effect.

With the environment ready, proceed to Chapter 2: First Script and Sync API.