第 1 章 · E2E 测试与 Playwright 概述
本章目标:理解 E2E 测试在测试金字塔中的位置,搞清 Playwright 相比 Selenium 的架构优势,装好 Playwright 并跑通环境。
1.1 测试金字塔中的 E2E
经典的测试金字塔从下到上分为三层:
| 层级 | 数量 | 速度 | 稳定性 | 验证内容 |
|---|---|---|---|---|
| 单元测试 | 最多 | 毫秒级 | 极稳 | 函数/类的逻辑 |
| 集成测试 | 适中 | 秒级 | 较稳 | 模块协作、数据库、API |
| E2E 测试 | 最少 | 十秒级 | 易碎 | 真实浏览器里的完整用户旅程 |
E2E(End-to-End,端到端)测试模拟的是"真实用户打开浏览器 → 操作页面 → 看到结果"的全过程。它慢且贵,但只有它能回答一个问题:用户实际用起来到底行不行。所以生产实践的原则是"少而精"——只覆盖关键路径(登录、下单、支付),而不是把所有分支都搬进来。
本教程的定位
本站 pytest 教程讲的是金字塔下半部分;本课程专注最顶层。两门课共用同一套 pytest 知识体系,第 6 章起会大量复用 fixture 技能。
1.2 Selenium WebDriver vs Playwright:架构决定体验
老一代方案 Selenium WebDriver 的工作方式是"外部遥控":
测试代码 → HTTP 请求 → WebDriver 驱动进程 → 浏览器扩展注入 JS → 页面每一步操作都要跨进程通信,且驱动不知道页面何时渲染完成,只能靠人肉 time.sleep(3) 或显式等待补救——这是 Selenium 时代测试易碎(flaky)的根源。
Playwright 的做法完全不同:测试进程通过直连浏览器的协议管道(Chromium 用 CDP,Firefox/WebKit 用补丁版内核内建协议)与浏览器对话:
测试代码 ←同一条持久连接→ 浏览器内核
(事件驱动,双向推送)这带来三个质变:
- 快:没有中间驱动层,操作直接下达给内核;
- 自动等待:内核知道页面的真实状态,Playwright 能在元素"可见、稳定、可交互"之前自动阻塞;
- 事件可靠:
click是真实的输入事件而非 JS 合成事件,还能监听网络、控制台等内核级信号。
1.3 三大浏览器内核
Playwright 支持 All modern rendering engines:
- Chromium——Chrome/Edge 的内核,日常默认;
- Firefox——打补丁的版本,可被自动化协议精确驱动;
- WebKit——Safari 的内核,在 Linux/Windows 上也能测 Safari 行为。
一套 API 跑三个引擎,意味着你在 Linux CI 上就能覆盖 Safari 兼容性,不再需要 Mac 机器农场。
1.4 同步与异步双 API
Playwright Python 同时提供 sync_api 和 async_api 两套镜像 API:
# 同步风格:直观,适合脚本和大多数测试
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()# 异步风格:适合 asyncio 应用和高并发爬取/压测场景
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())两套 API 功能完全对等,异步版只是每个方法多了 await。前半程课程以同步为主,第 18 章专门讲异步。
1.5 安装与环境验证
# 安装库本体
pip install playwright
# 下载三大内核(一次即可,约几百 MB)
playwright install
# 可选:安装系统依赖(Linux 常需要)
playwright install-deps验证安装是否成功:
playwright --version
# Version 1.62.x再跑一个最小冒烟脚本 smoke.py:
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(), "标题不符合预期"
print("✅ 环境正常,标题:", page.title())
browser.close()python smoke.py
# ✅ 环境正常,标题: Example Domain版本对应关系
playwright pip 包与浏览器内核是配套锁定的:升级 pip 包后必须重新执行 playwright install 下载新版本内核,否则会报找不到可执行文件的错误。
1.6 本章小结
- E2E 位于测试金字塔顶端:少而精,只测关键用户路径;
- Playwright 直连浏览器内核协议,相比 Selenium 更快、自动等待、事件更真实;
- 一套 API 覆盖 Chromium / Firefox / WebKit 三大内核;
- 提供
sync_api/async_api两套对等 API; - 升级 Playwright 后记得重跑
playwright install。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. Playwright 与 Selenium WebDriver 最本质的架构差异是?
2. 想在 Linux CI 上验证 Safari 兼容性,应该用哪个内核?
3. 升级 playwright pip 包后运行报"找不到浏览器可执行文件",原因是?
4. 关于 sync_api 和 async_api,下列说法正确的是?
🛠️ 动手实践
- 用同步 API 写一个脚本,依次访问
example.com和playwright.dev,分别打印<title>。 - 把第 1 题改写成异步版本,对比两种写法的差异。
- 分别用 headless 和 headed(
headless=False)模式运行你的脚本,观察区别;再加slow_mo=1000感受慢放效果。
环境就绪后,进入第 2 章:第一个脚本与同步 API。