Python+Playwright 自动化测试实战指南

张开发
2026/4/16 22:57:35 15 分钟阅读

分享文章

Python+Playwright 自动化测试实战指南
1. 为什么选择Playwright做自动化测试最近几年自动化测试工具层出不穷但Playwright凭借其独特的优势迅速成为测试开发者的新宠。作为一个从Selenium时代一路走过来的老测试我不得不说Playwright确实解决了很多痛点问题。首先它原生支持多语言Python、JavaScript、TypeScript、Java、.NET都能用这对团队协作特别友好。其次它内置了Chromium、Firefox和WebKit三大浏览器引擎不需要额外配置驱动开箱即用。在实际项目中我发现Playwright的等待机制特别智能。传统工具最头疼的元素加载问题Playwright会自动等待元素可交互状态才执行操作再也不用写一堆sleep了。记得有一次测试电商下单流程页面有多个异步加载环节用Playwright一条page.click()就搞定了而同样的场景用其他工具要写复杂的等待逻辑。性能方面也让人惊喜。我做过对比测试同样的100个测试用例Playwright比传统方案快30%左右。这得益于它的底层架构优化比如单个浏览器实例可以复用多个页面上下文。对于需要频繁切换场景的测试特别有用。2. 环境搭建与快速入门2.1 安装准备开始前建议准备Python 3.7环境我习惯用pyenv管理多版本Python。安装过程非常简单只需要两条命令pip install playwright playwright install第一条安装Python包第二条会自动下载Chromium、Firefox和WebKit的适配版本。这里有个小技巧如果网络环境不好可以设置镜像源加速下载PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright playwright install第一次安装可能会比较耗时因为要下载三个浏览器引擎。我实测在MacBook Pro上大概需要5-10分钟取决于网络速度。安装完成后可以验证下python -m playwright --version2.2 第一个测试脚本创建一个demo.py文件我们来写个最简单的百度搜索测试from playwright.sync_api import sync_playwright with sync_playwright() as p: # 启动浏览器设置headlessFalse可以看到界面 browser p.chromium.launch(headlessFalse) page browser.new_page() # 访问百度 page.goto(https://www.baidu.com) # 输入搜索词 page.fill(#kw, Playwright自动化测试) # 点击搜索按钮 page.click(#su) # 等待结果加载 page.wait_for_selector(.result-op) # 截图保存 page.screenshot(pathsearch_result.png) # 关闭浏览器 browser.close()运行这个脚本你会看到浏览器自动打开完成搜索操作后保存截图。这就是Playwright的基本工作流程启动浏览器→打开页面→执行操作→验证结果。3. 核心API实战技巧3.1 元素定位的十八般武艺定位元素是自动化测试的基础Playwright提供了丰富的方式# CSS选择器 page.click(button.submit) # XPath page.fill(//input[idusername], testuser) # 文本定位 page.click(text登录) # 组合定位 page.click(#nav text首页)实际项目中我总结了几点经验优先使用CSS选择器性能最好动态ID的元素可以用属性选择器如[data-testidlogin-btn]文本定位要小心多语言场景复杂的层级可以用组合定位遇到iframe怎么办Playwright处理起来特别简单# 定位iframe元素 frame page.frame_locator(iframe#login).first # 在iframe内操作 frame.fill(#username, admin)3.2 等待与断言的艺术Playwright内置智能等待但有时需要更精细的控制# 等待元素出现 page.wait_for_selector(.toast, statevisible) # 等待网络请求完成 page.wait_for_response(**/api/data) # 自定义等待条件 page.wait_for_function(() { return document.readyState complete })断言是测试的核心Playwright推荐这样写# 文本包含断言 assert 订单创建成功 in page.inner_text(#msg) # 元素可见断言 assert page.is_visible(.success-icon) # 自定义断言 expect(page).to_have_url(re.compile(r\/order\/\d))4. 高级应用场景4.1 模拟移动端测试测试响应式页面时设备模拟非常有用iphone p.devices[iPhone 12] browser p.chromium.launch() context browser.new_context(**iphone) page context.new_page() page.goto(https://m.example.com)Playwright内置了30种设备参数包括视口大小、UserAgent、DPI等。如果需要自定义设备也很简单custom_device { user_agent: Mozilla/5.0..., viewport: {width: 375, height: 812}, device_scale_factor: 3 }4.2 网络请求拦截这个功能在测试前后端分离应用时特别给力# Mock API响应 def handle_route(route): if /api/user in route.request.url: route.fulfill(json{name: Mock User}) else: route.continue_() page.route(**/api/**, handle_route)我常用这个技巧来模拟异常场景如500错误加速测试跳过真实API调用测试边缘情况如超大响应数据4.3 自动化测试集成结合pytest可以构建完整的测试套件import pytest from playwright.sync_api import expect pytest.fixture(scopemodule) def page(): with sync_playwright() as p: browser p.chromium.launch() context browser.new_context() page context.new_page() yield page browser.close() def test_login(page): page.goto(https://example.com/login) page.fill(#username, test) page.fill(#password, pass123) page.click(#login-btn) expect(page).to_have_url(https://example.com/dashboard)建议的目录结构tests/ ├── conftest.py # 公共fixture ├── test_login.py ├── test_order.py └── utils/ # 公共方法5. 性能优化与调试5.1 测试加速技巧复用浏览器上下文pytest.fixture def context(browser): context browser.new_context() yield context context.close()并行执行测试pytest -n auto # 使用pytest-xdist插件选择性安装浏览器playwright install chromium # 只安装需要的浏览器5.2 调试技巧开启调试模式browser p.chromium.launch( headlessFalse, devtoolsTrue, slow_mo500 # 放慢操作便于观察 )日志记录DEBUGpw:api pytest # 显示详细API日志遇到元素定位问题时可以先用codegen工具录制操作playwright codegen https://example.com6. 企业级实践建议在大型项目中我推荐这些实践使用Page Object模式封装页面class LoginPage: def __init__(self, page): self.page page self.username page.locator(#username) self.password page.locator(#password) def login(self, user, pwd): self.username.fill(user) self.password.fill(pwd) self.page.click(#submit)配置全局超时时间# conftest.py pytest.fixture(scopesession) def browser_context_args(browser_context_args): return { **browser_context_args, default_timeout: 10000 }失败时自动截图pytest.hookimpl(hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.failed and page in item.funcargs: page item.funcargs[page] screenshot page.screenshot(pathferror_{item.name}.png) report.extra.append(pytest_html.extras.image(screenshot))集成CI/CD流程# GitHub Actions示例 jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv2 - uses: actions/setup-pythonv2 - run: pip install -r requirements.txt - run: playwright install - run: pytest --htmlreport.html - uses: actions/upload-artifactv2 if: always() with: name: test-reports path: | report.html *.png

更多文章