闲社

标题: 【教程】用Python+Playwright打造自动化测试框架:从零搭建到CI/CD集成 [打印本页]

作者: gue3004    时间: 昨天 17:17
标题: 【教程】用Python+Playwright打造自动化测试框架:从零搭建到CI/CD集成
【教程】用Python+Playwright打造自动化测试框架:从零搭建到CI/CD集成

一、前置条件

在开始之前,请确保你的环境满足以下条件:



二、为什么选Playwright?

最近uniTerm v1.0正式开源发布,深度集成AI Agent的终端智能能力引发热议。而在Web自动化测试领域,Playwright正以碾压之势取代Selenium成为新标杆。

核心优势:


三、步骤1:环境搭建
  1. # 创建项目目录
  2. mkdir playwright-demo && cd playwright-demo
  3. # 创建虚拟环境
  4. python -m venv venv
  5. source venv/bin/activate  # Linux/Mac
  6. # venv\Scripts\activate  # Windows
  7. # 安装Playwright
  8. pip install pytest-playwright
  9. # 安装浏览器二进制文件
  10. playwright install
复制代码

验证安装:
  1. playwright --version
  2. # 输出类似:Version 1.49.0
复制代码

四、步骤2:编写第一个测试

创建 test_example.py
  1. import re
  2. from playwright.sync_api import Page, expect
  3. def test_has_title(page: Page):
  4.     page.goto("https://playwright.dev/")
  5.    
  6.     # 断言页面标题包含Playwright
  7.     expect(page).to_have_title(re.compile("Playwright"))
  8. def test_get_started_link(page: Page):
  9.     page.goto("https://playwright.dev/")
  10.    
  11.     # 点击Get started链接
  12.     page.get_by_role("link", name="Get started").click()
  13.    
  14.     # 断言页面URL包含intro
  15.     expect(page).to_have_url(re.compile(".*intro"))
复制代码

运行测试:
  1. pytest test_example.py --headed  # 有界面模式
  2. pytest test_example.py          # 无头模式(推荐CI使用)
复制代码

五、步骤3:Page Object模式实战

对于复杂项目,推荐Page Object模式组织代码。以登录功能为例:

创建 pages/login_page.py
  1. from playwright.sync_api import Page
  2. class LoginPage:
  3.     def __init__(self, page: Page):
  4.         self.page = page
  5.         self.username_input = page.locator("#username")
  6.         self.password_input = page.locator("#password")
  7.         self.login_button = page.locator("button[type='submit']")
  8.         self.error_message = page.locator(".alert-danger")
  9.    
  10.     def navigate(self, url: str):
  11.         self.page.goto(url)
  12.         return self
  13.    
  14.     def login(self, username: str, password: str):
  15.         self.username_input.fill(username)
  16.         self.password_input.fill(password)
  17.         self.login_button.click()
  18.         return self
  19.    
  20.     def get_error_text(self) -> str:
  21.         return self.error_message.inner_text()
复制代码

创建 test_login.py
  1. import pytest
  2. from playwright.sync_api import Page
  3. from pages.login_page import LoginPage
  4. class TestLogin:
  5.     def test_successful_login(self, page: Page):
  6.         login_page = LoginPage(page)
  7.         login_page.navigate("https://example.com/login")
  8.         login_page.login("admin", "correct_password")
  9.         
  10.         # 断言登录成功后的跳转
  11.         assert page.url == "https://example.com/dashboard"
  12.    
  13.     def test_failed_login(self, page: Page):
  14.         login_page = LoginPage(page)
  15.         login_page.navigate("https://example.com/login")
  16.         login_page.login("admin", "wrong_password")
  17.         
  18.         # 断言错误提示
  19.         error_text = login_page.get_error_text()
  20.         assert "用户名或密码错误" in error_text
复制代码

六、步骤4:数据驱动与参数化

使用pytest参数化实现数据驱动:
  1. import pytest
  2. from playwright.sync_api import Page
  3. from pages.login_page import LoginPage
  4. @pytest.mark.parametrize("username,password,expected", [
  5.     ("admin", "correct_pass", "success"),
  6.     ("admin", "wrong_pass", "error"),
  7.     ("", "", "error"),
  8.     ("invalid_user", "any_pass", "error"),
  9. ])
  10. def test_login_scenarios(page: Page, username, password, expected):
  11.     login_page = LoginPage(page)
  12.     login_page.navigate("https://example.com/login")
  13.     login_page.login(username, password)
  14.    
  15.     if expected == "success":
  16.         assert "dashboard" in page.url
  17.     else:
  18.         error_text = login_page.get_error_text()
  19.         assert len(error_text) > 0
复制代码

七、步骤5:CI/CD集成(GitHub Actions)

创建 .github/workflows/playwright.yml
  1. name: Playwright Tests
  2. on:
  3.   push:
  4.     branches: [main, develop]
  5.   pull_request:
  6.     branches: [main]
  7. jobs:
  8.   test:
  9.     runs-on: ubuntu-latest
  10.     steps:
  11.       - uses: actions/checkout@v4
  12.       
  13.       - name: Set up Python
  14.         uses: actions/setup-python@v5
  15.         with:
  16.           python-version: '3.11'
  17.       
  18.       - name: Install dependencies
  19.         run: |
  20.           pip install pytest-playwright
  21.           playwright install --with-deps
  22.       
  23.       - name: Run tests
  24.         run: pytest --tracing=retain-on-failure
  25.       
  26.       - name: Upload trace
  27.         if: failure()
  28.         uses: actions/upload-artifact@v4
  29.         with:
  30.           name: playwright-traces
  31.           path: test-results/
复制代码

八、步骤6:高级技巧

1. 自动录制视频与截图
  1. # pytest.ini
  2. [pytest]
  3. addopts = --video=retain-on-failure --screenshot=only-on-failure
复制代码

2. 移动端模拟
  1. from playwright.sync_api import sync_playwright
  2. with sync_playwright() as p:
  3.     iphone = p.devices['iPhone 14']
  4.     browser = p.chromium.launch()
  5.     context = browser.new_context(**iphone)
  6.     page = context.new_page()
  7.     page.goto('https://example.com')
复制代码

3. API拦截与Mock
  1. # 拦截API请求并返回Mock数据
  2. page.route("**/api/users", lambda route: route.fulfill(
  3.     status=200,
  4.     content_type="application/json",
  5.     body='{"users": [{"id": 1, "name": "Mock User"}]}'
  6. ))
复制代码

九、常见问题

Q1: 测试在CI中失败,本地正常?
A: 通常是等待时间问题。Playwright的自动等待已很智能,但复杂异步加载场景建议增加显式等待:
  1. page.wait_for_load_state('networkidle')
复制代码

Q2: 如何处理动态变化的元素定位?
A: 优先使用语义化定位(get_by_role/get_by_text),避免依赖CSS选择器:
  1. page.get_by_role("button", name="提交").click()
复制代码

Q3: 测试执行太慢?
A: 启用并行执行:
  1. pytest -n auto  # 需要安装pytest-xdist
复制代码

Q4: 如何调试失败的测试?
A: 使用Trace Viewer:
  1. pytest --tracing=on
  2. playwright show-trace trace.zip
复制代码

十、总结

通过本教程,我们完成了:


Playwright的生态系统正在快速成熟,配合pytest的强大功能,可以构建企业级的自动化测试体系。建议下一步学习:


参考资料:
Playwright Python官方文档
Playwright Python GitHub

本教程基于Playwright v1.49+编写,如有更新请以官方文档为准。




欢迎光临 闲社 (https://www.xianshe.com/) Powered by Discuz! X5.0