专栏 :Playwright Python 实战专栏 · 预计阅读:12 分钟 ·
1. 为什么选择 pytest-playwright

pytest-playwright 将 Playwright 的浏览器能力封装为函数级 fixture:playwright、browser、context 和 page。测试只需声明依赖,框架负责启动与回收。这样既能复用 pytest 的收集、参数化和插件机制,又能让每个测试默认获得干净的 context 与 page。1
2. 环境要求与安装
建议 Python 3.10 及以上版本;Playwright 通过独立浏览器二进制保证跨平台一致性。安装分为两步:Python 包与浏览器。
bash
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install playwright pytest pytest-playwright
playwright install chromium
说明 :Windows PowerShell 使用
.venv\Scripts\Activate.ps1。若 CI 已缓存浏览器,可仅安装当前项目需要的浏览器。
3. 最小项目结构
将配置、页面对象和测试分层,可以让第 8、9 篇的复杂场景仍可维护。
text
playwright-python-series/
├── pytest.ini
├── conftest.py
├── requirements.txt
├── pages/
│ └── login_page.py
└── tests/
└── test_login.py
4. pytest.ini:让配置可复现
ini
[pytest]
testpaths = tests
addopts =
-v
--browser chromium
--headed
--base-url http://localhost:3000
--base-url 与 page.goto("/") 配合,可在不同环境间切换。addopts 用于团队默认值,个人临时调试仍可直接覆盖 CLI 参数。1
5. 第一个 test_ 用例
python
from playwright.sync_api import Page, expect
def test_page_title(page: Page) -> None:
page.goto("/")
expect(page).to_have_title("Playwright Demo")
test_ 前缀使 pytest 自动收集;page: Page 由插件注入。不要将 page 保存为模块级全局变量,否则会破坏测试隔离。
6. 使用 codegen 生成可修改的起点
bash
playwright codegen --target python-pytest http://localhost:3000
codegen 的价值是快速发现角色、文本和测试 ID,而不是把录制结果原样提交。应将其改写为第 2 篇的语义定位器,并补充第 3 篇的 expect 断言。
7. 登录示例:操作之后必须有断言
python
from playwright.sync_api import Page, expect
def test_login_success(page: Page) -> None:
page.goto("/login")
page.get_by_label("Username").fill("demo")
page.get_by_label("Password").fill("secret")
page.get_by_role("button", name="Sign in").click()
expect(page.get_by_test_id("welcome")).to_be_visible()
点击后没有断言,只能证明"脚本没有抛异常",不能证明业务成功。将"行为"与"验收"配对,是本专栏贯穿始终的纪律。
8. 运行与失败诊断
bash
pytest tests/test_login.py -k login
pytest tests/test_login.py --tracing retain-on-failure
失败时优先阅读追踪(trace)、截图和动作日志,再决定是否增加等待。Playwright 已内置动作可操作性等待,避免用 time.sleep 掩盖竞态。
9. 依赖锁定
text
playwright>=1.45
pytest>=8.0
pytest-playwright>=0.8
固定主要版本可避免团队成员或 CI 间出现行为漂移。浏览器版本由 playwright install 的包版本决定,也应纳入镜像或缓存策略。
10. 从脚本到工程化
第一篇不是"打开浏览器"的演示,而是建立可重复执行的工程边界:Python 环境、配置、命名、断言和诊断工具。后续 8 篇均在此结构上增加定位、等待、控件和跨文档能力。
11. 常见问题速查
| 现象 | 优先检查 | 正确方向 |
|---|---|---|
page 未注入 |
函数参数、同步 API 混用 | 使用 def test_xxx(page) |
| 找不到浏览器 | 未执行 playwright install |
安装对应浏览器 |
| 录制代码脆弱 | CSS/XPath 过长 | 改用 role/text/test ID |
12. 小结
- Python 环境与浏览器二进制必须分别安装。
pytest.ini固化团队运行约定,但不替代可读的测试代码。- 每个操作都必须有可观察的
expect验收。
13. 思考题
- 为什么
page适合作为函数参数,而不是全局对象? - 如何用
--base-url区分开发、测试与生产环境? - codegen 生成的定位器应在何时重写?
14. 下一篇预告
第 2 篇将系统讲解定位器:从 page.locator() 到 get_by_role,形成稳定、可调试的查找策略。