Access Denied (103) 【教程】用Python+Playwright打造自动化测试框架:从零搭建到CI/CD集成 - 技能分享 - 闲社 - Powered by Discuz! Archiver

gue3004 发表于 1 小时前

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

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

一、前置条件

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


[*]Python 3.8+ 已安装
[*]pip 包管理器可用
[*]一个代码编辑器(推荐 VS Code)
[*]Git 已安装(用于版本管理)


二、为什么选Playwright?

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

核心优势:

[*]自动等待:告别time.sleep(),元素操作自动等待就绪
[*]多浏览器:Chromium、Firefox、WebKit一键切换
[*]录制生成:codegen命令自动生成测试代码
[*]Trace Viewer:可视化回溯测试执行过程
[*]并行执行:原生支持多worker并发测试


三、步骤1:环境搭建


# 创建项目目录
mkdir playwright-demo && cd playwright-demo

# 创建虚拟环境
python -m venv venv
source venv/bin/activate# Linux/Mac
# venv\Scripts\activate# Windows

# 安装Playwright
pip install pytest-playwright

# 安装浏览器二进制文件
playwright install


验证安装:

playwright --version
# 输出类似:Version 1.49.0


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

创建 test_example.py:


import re
from playwright.sync_api import Page, expect

def test_has_title(page: Page):
    page.goto("https://playwright.dev/")
   
    # 断言页面标题包含Playwright
    expect(page).to_have_title(re.compile("Playwright"))

def test_get_started_link(page: Page):
    page.goto("https://playwright.dev/")
   
    # 点击Get started链接
    page.get_by_role("link", name="Get started").click()
   
    # 断言页面URL包含intro
    expect(page).to_have_url(re.compile(".*intro"))


运行测试:

pytest test_example.py --headed# 有界面模式
pytest test_example.py          # 无头模式(推荐CI使用)


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

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

创建 pages/login_page.py:


from playwright.sync_api import Page

class LoginPage:
    def __init__(self, page: Page):
      self.page = page
      self.username_input = page.locator("#username")
      self.password_input = page.locator("#password")
      self.login_button = page.locator("button")
      self.error_message = page.locator(".alert-danger")
   
    def navigate(self, url: str):
      self.page.goto(url)
      return self
   
    def login(self, username: str, password: str):
      self.username_input.fill(username)
      self.password_input.fill(password)
      self.login_button.click()
      return self
   
    def get_error_text(self) -> str:
      return self.error_message.inner_text()


创建 test_login.py:


import pytest
from playwright.sync_api import Page
from pages.login_page import LoginPage

class TestLogin:
    def test_successful_login(self, page: Page):
      login_page = LoginPage(page)
      login_page.navigate("https://example.com/login")
      login_page.login("admin", "correct_password")
      
      # 断言登录成功后的跳转
      assert page.url == "https://example.com/dashboard"
   
    def test_failed_login(self, page: Page):
      login_page = LoginPage(page)
      login_page.navigate("https://example.com/login")
      login_page.login("admin", "wrong_password")
      
      # 断言错误提示
      error_text = login_page.get_error_text()
      assert "用户名或密码错误" in error_text


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

使用pytest参数化实现数据驱动:


import pytest
from playwright.sync_api import Page
from pages.login_page import LoginPage

@pytest.mark.parametrize("username,password,expected", [
    ("admin", "correct_pass", "success"),
    ("admin", "wrong_pass", "error"),
    ("", "", "error"),
    ("invalid_user", "any_pass", "error"),
])
def test_login_scenarios(page: Page, username, password, expected):
    login_page = LoginPage(page)
    login_page.navigate("https://example.com/login")
    login_page.login(username, password)
   
    if expected == "success":
      assert "dashboard" in page.url
    else:
      error_text = login_page.get_error_text()
      assert len(error_text) > 0


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

创建 .github/workflows/playwright.yml:


name: Playwright Tests

on:
push:
    branches:
pull_request:
    branches:

jobs:
test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
      uses: actions/setup-python@v5
      with:
          python-version: '3.11'
      
      - name: Install dependencies
      run: |
          pip install pytest-playwright
          playwright install --with-deps
      
      - name: Run tests
      run: pytest --tracing=retain-on-failure
      
      - name: Upload trace
      if: failure()
      uses: actions/upload-artifact@v4
      with:
          name: playwright-traces
          path: test-results/


八、步骤6:高级技巧

1. 自动录制视频与截图


# pytest.ini

addopts = --video=retain-on-failure --screenshot=only-on-failure


2. 移动端模拟


from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    iphone = p.devices['iPhone 14']
    browser = p.chromium.launch()
    context = browser.new_context(**iphone)
    page = context.new_page()
    page.goto('https://example.com')


3. API拦截与Mock


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


九、常见问题

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

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

Q3: 测试执行太慢?
A: 启用并行执行:
pytest -n auto# 需要安装pytest-xdist

Q4: 如何调试失败的测试?
A: 使用Trace Viewer:

pytest --tracing=on
playwright show-trace trace.zip


十、总结

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

[*]Playwright环境搭建与基础测试编写
[*]Page Object模式实现代码复用
[*]参数化实现数据驱动测试
[*]GitHub Actions CI/CD流水线集成
[*]视频录制、移动端模拟、API Mock等高级技巧


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

[*]视觉回归测试(playwright-snapshot)
[*]测试报告集成(Allure/Playwright HTML Report)
[*]分布式测试执行(Selenium Grid替代方案)


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

本教程基于Playwright v1.49+编写,如有更新请以官方文档为准。
页: [1]
查看完整版本: 【教程】用Python+Playwright打造自动化测试框架:从零搭建到CI/CD集成