当前位置: 首页 > news >正文

Playwright与Python:从入门到精通的完整指南

前言

在当今快速迭代的软件开发环境中,自动化测试已成为保证产品质量的关键。Playwright作为微软推出的新一代测试框架,凭借其卓越的性能和丰富的功能,正在重新定义Web自动化测试的标准。本文将带您从零开始,全面掌握使用Playwright生成Python自动化脚本的技能。

第一部分:Playwright基础入门

1.1 Playwright简介

Playwright的核心优势:
• 🔥 跨浏览器支持:Chromium、Firefox、WebKit

• ⚡ 自动等待机制:智能等待元素,减少Flaky测试

• 🎯 强大的选择器引擎:文本、CSS、XPath等多种定位方式

• 🌐 网络拦截能力:模拟各种网络条件

• 📱 移动端测试:完整的移动设备模拟

1.2 环境安装与配置

系统要求检查

检查Python版本(需要3.7+)

python --version

检查pip版本

pip --version

安装Playwright

安装Playwright Python包

pip install playwright

安装浏览器(推荐全部安装)

playwright install
playwright install chromium
playwright install firefox
playwright install webkit

验证安装

python -c “import playwright; print(‘安装成功’)”

开发环境配置

// .vscode/settings.json(VS Code配置)
{
“python.testing.pytestEnabled”: true,
“python.testing.unittestEnabled”: false,
“python.testing.pytestArgs”: [
“tests”
]
}

第二部分:代码生成器深度解析

2.1 基础录制功能

启动代码生成器

基本录制

playwright codegen

录制指定网站

playwright codegen https://example.com

生成Python脚本

playwright codegen --target python -o my_script.py

指定浏览器录制

playwright codegen --browser firefox https://example.com

录制参数详解

完整参数示例

playwright codegen https://example.com
–target python \ # 生成Python代码
–output test_example.py \ # 输出文件
–browser chromium \ # 指定浏览器
–viewport-size 1280,720 \ # 设置视口
–user-agent “Custom UA” \ # 自定义User-Agent
–save-storage auth.json \ # 保存登录状态
–load-storage auth.json # 加载登录状态

2.2 高级录制技巧

移动端录制

模拟移动设备

playwright codegen
–device=“iPhone 12”
–viewport-size=“390,844”
https://m.example.com

可用设备列表

playwright codegen --help | grep device

认证状态管理

第一步:录制登录过程并保存状态

playwright codegen https://example.com/login --save-storage auth.json

第二步:使用保存的状态录制其他页面

playwright codegen https://example.com/dashboard --load-storage auth.json

2.3 自定义录制模板

custom_recorder.py

from playwright.sync_api import sync_playwright
import json
from datetime import datetime

class AdvancedRecorder:
def init(self, base_url, config=None):
self.base_url = base_url
self.config = config or {}
self.actions = []

def start_recording(self, output_file="recorded_script.py"):"""开始录制会话"""with sync_playwright() as p:# 浏览器配置browser = p.chromium.launch(headless=False,args=['--start-maximized'])# 上下文配置context = browser.new_context(viewport=self.config.get('viewport', {'width': 1920, 'height': 1080}),user_agent=self.config.get('user_agent'),ignore_https_errors=True)# 开始跟踪context.tracing.start(screenshots=True, snapshots=True)page = context.new_page()# 导航到目标页面page.goto(self.base_url)print(f"开始录制: {self.base_url}")print("操作浏览器,按 Ctrl+C 结束录制...")try:self._record_actions(page)except KeyboardInterrupt:self._generate_script(output_file, context)finally:browser.close()def _record_actions(self, page):"""录制用户操作"""# 这里可以添加自定义录制逻辑import timewhile True:time.sleep(0.1)def _generate_script(self, output_file, context):"""生成优化后的脚本"""script_template = self._create_script_template()with open(output_file, 'w', encoding='utf-8') as f:f.write(script_template)print(f"脚本已生成: {output_file}")# 保存跟踪信息context.tracing.stop(path="recording-trace.zip")

使用示例

recorder = AdvancedRecorder(“https://example.com”)
recorder.start_recording(“optimized_test.py”)

第三部分:Playwright Python API精通

3.1 核心API详解

浏览器管理

from playwright.sync_api import sync_playwright

def browser_management_examples():
with sync_playwright() as p:
# 浏览器启动选项
browser = p.chromium.launch(
headless=False, # 显示浏览器
slow_mo=100, # 慢动作(毫秒)
devtools=True, # 打开开发者工具
args=[‘–start-maximized’] # 启动参数
)

    # 浏览器上下文context = browser.new_context(viewport={'width': 1920, 'height': 1080},user_agent='自定义User-Agent',ignore_https_errors=True,java_script_enabled=True)# 创建页面page = context.new_page()# 页面基本操作page.goto('https://example.com')page.reload()page.go_back()page.go_forward()browser.close()

异步版本

import asyncio
from playwright.async_api import async_playwright

async def async_browser_management():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto(‘https://example.com’)
await browser.close()

3.2 元素定位高级技巧

选择器大全

def selector_masterclass(page):
# CSS选择器
page.click(‘button.submit’)
page.click(‘.btn-primary’)
page.click(‘#login-btn’)

# 文本选择器
page.click('text=登录')
page.click("'精确文本匹配'")
page.click('text=/正则表达式.*/')# XPath选择器
page.click('//button[@id="submit"]')
page.click('//div[contains(@class, "error")]')# 组合选择器
page.click('div.error >> text=重试')
page.click('form#login >> input[name="username"]')# 相对定位器
page.click('input:near(:text("用户名"))')
page.click('button:right-of(:text("搜索"))')# 可视化定位器
page.click('button:has-text("提交")')
page.click('div:has(> img.logo)')

最佳实践:使用Locator对象

def locator_best_practices(page):
# 创建Locator对象
submit_btn = page.locator(‘button:has-text(“提交”)’)
username_input = page.locator(‘#username’)

# Locator操作
submit_btn.click()
username_input.fill('testuser')# 链式操作
page.locator('form.login').locator('input[type="text"]').fill('value')# 等待元素
submit_btn.wait_for(state='visible')

3.3 高级交互操作

def advanced_interactions(page):
# 键盘操作
page.keyboard.press(‘Enter’)
page.keyboard.type(‘Hello World’)
page.keyboard.down(‘Shift’)

# 鼠标操作
page.mouse.click(100, 200)
page.mouse.dblclick(150, 250)
page.mouse.down()
page.mouse.move(300, 400)
page.mouse.up()# 拖放操作
page.drag_and_drop('#source', '#target')# 文件操作
page.set_input_files('input[type="file"]', 'file.txt')
page.set_input_files('input[type="file"]', ['file1.txt', 'file2.txt'])# 焦点和标签页管理
page.bring_to_front()
page.evaluate('window.focus()')

处理复杂场景

def handle_complex_scenarios(page):
# 滚动操作
page.evaluate(‘window.scrollTo(0, document.body.scrollHeight)’)
page.mouse.wheel(0, 100)

# 执行JavaScript
page.evaluate('() => document.title')
result = page.evaluate('(x) => x * 2', 5)# 元素状态检查
is_visible = page.is_visible('selector')
is_enabled = page.is_enabled('selector')
is_checked = page.is_checked('selector')

第四部分:测试框架集成

4.1 Pytest集成

基础配置

conftest.py

import pytest
from playwright.sync_api import Page, Browser

@pytest.fixture(scope=“session”)
def browser():
“”“全局浏览器实例”“”
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
yield browser
browser.close()

@pytest.fixture
def context(browser):
“”“测试上下文”“”
context = browser.new_context()
yield context
context.close()

@pytest.fixture
def page(context):
“”“测试页面”“”
page = context.new_page()
yield page
page.close()

配置文件 pytest.ini

[pytest]
addopts = -v --tb=short --strict-markers
markers =
slow: 慢速测试
ui: UI测试
api: API测试

测试用例编写

test_example.py

import pytest
from playwright.sync_api import Page, expect

class TestLogin:
“”“登录功能测试”“”

@pytest.fixture(autouse=True)
def setup(self, page: Page):"""测试前置条件"""self.page = pageself.page.goto("https://example.com/login")def test_successful_login(self):"""测试成功登录"""# 操作步骤self.page.fill("#username", "testuser")self.page.fill("#password", "correctpassword")self.page.click("#login-btn")# 断言验证expect(self.page).to_have_url("https://example.com/dashboard")expect(self.page.locator(".welcome-message")).to_contain_text("欢迎")def test_login_failure(self):"""测试登录失败"""self.page.fill("#username", "wronguser")self.page.fill("#password", "wrongpassword")self.page.click("#login-btn")expect(self.page.locator(".error-message")).to_be_visible()expect(self.page.locator(".error-message")).to_contain_text("用户名或密码错误")

@pytest.mark.ui
@pytest.mark.slow
class TestE2E:
“”“端到端测试”“”

def test_complete_user_journey(self, page: Page):"""完整用户流程测试"""# 登录page.goto("https://example.com/login")page.fill("#username", "testuser")page.fill("#password", "password123")page.click("#login-btn")# 导航到功能页面page.click("text=仪表板")expect(page).to_have_url("**/dashboard")# 执行操作page.click("button.new-item")page.fill("#item-name", "测试项目")page.click("#save-btn")# 验证结果expect(page.locator(".success-message")).to_be_visible()

4.2 页面对象模式(Page Object Model)

pages/base_page.py

from playwright.sync_api import Page, expect
from typing import Tuple

class BasePage:
“”“页面基类”“”

def __init__(self, page: Page):self.page = pageself.timeout = 30000def wait_for_loading(self):"""等待页面加载完成"""self.page.wait_for_load_state("networkidle")def take_screenshot(self, name: str):"""截图"""self.page.screenshot(path=f"screenshots/{name}.png")def get_element(self, selector: str):"""获取元素"""return self.page.locator(selector)

pages/login_page.py

from .base_page import BasePage

class LoginPage(BasePage):
“”“登录页面”“”

# 元素定位器
USERNAME_INPUT = "#username"
PASSWORD_INPUT = "#password"
LOGIN_BUTTON = "#login-btn"
ERROR_MESSAGE = ".error-message"def __init__(self, page: Page):super().__init__(page)self.url = "https://example.com/login"def navigate(self):"""导航到登录页面"""self.page.goto(self.url)self.wait_for_loading()def login(self, username: str, password: str):"""执行登录操作"""self.page.fill(self.USERNAME_INPUT, username)self.page.fill(self.PASSWORD_INPUT, password)self.page.click(self.LOGIN_BUTTON)def get_error_message(self) -> str:"""获取错误消息"""return self.page.text_content(self.ERROR_MESSAGE)def is_login_successful(self) -> bool:"""检查登录是否成功"""return "dashboard" in self.page.url

pages/dashboard_page.py

from .base_page import BasePage

class DashboardPage(BasePage):
“”“仪表板页面”“”

WELCOME_MESSAGE = ".welcome-message"
NEW_ITEM_BUTTON = "button.new-item"def __init__(self, page: Page):super().__init__(page)def is_loaded(self) -> bool:"""检查页面是否加载完成"""return self.page.locator(self.WELCOME_MESSAGE).is_visible()def create_new_item(self, item_name: str):"""创建新项目"""self.page.click(self.NEW_ITEM_BUTTON)# 更多创建逻辑...

使用页面对象

def test_with_page_objects(login_page: LoginPage, dashboard_page: DashboardPage):
“”“使用页面对象模式的测试”“”
login_page.navigate()
login_page.login(“testuser”, “password123”)

assert dashboard_page.is_loaded()
assert "欢迎" in dashboard_page.get_welcome_message()

第五部分:高级特性与最佳实践

5.1 网络拦截与模拟

def network_interception_examples(page):
“”“网络拦截示例”“”

# 拦截API请求
async def handle_request(route, request):if "api/users" in request.url:# 模拟响应await route.fulfill(status=200,content_type="application/json",body=json.dumps({"users": []}))else:await route.continue_()# 设置路由
await page.route("**/api/**", handle_request)# 监控网络活动
def log_request(request):print(f"请求: {request.method} {request.url}")def log_response(response):print(f"响应: {response.status} {response.url}")page.on("request", log_request)
page.on("response", log_response)# 模拟慢网络
async def slow_mobile_network(route, request):# 添加延迟模拟慢网络await asyncio.sleep(2)await route.continue_()await page.route("**/*", slow_mobile_network)

5.2 性能测试与监控

performance_monitor.py

import time
from playwright.sync_api import Page

class PerformanceMonitor:
“”“性能监控器”“”

def __init__(self, page: Page):self.page = pageself.metrics = {}def start_monitoring(self):"""开始性能监控"""self.page.evaluate("""window.performanceMetrics = {startTime: performance.now(),marks: {}};""")def mark(self, name: str):"""添加性能标记"""self.page.evaluate(f"window.performanceMetrics.marks['{name}'] = performance.now();")def get_metrics(self) -> dict:"""获取性能指标"""return self.page.evaluate("""() => {const metrics = window.performanceMetrics;const navigation = performance.getEntriesByType('navigation')[0];return {loadTime: navigation.loadEventEnd - navigation.navigationStart,domContentLoaded: navigation.domContentLoadedEventEnd - navigation.navigationStart,marks: metrics.marks,memory: performance.memory};}""")

使用示例

def test_performance(login_page: LoginPage):
monitor = PerformanceMonitor(login_page.page)
monitor.start_monitoring()

login_page.navigate()
monitor.mark("page_loaded")login_page.login("user", "pass")
monitor.mark("login_completed")metrics = monitor.get_metrics()
assert metrics["loadTime"] < 3000  # 页面加载应小于3秒

5.3 持续集成配置

.github/workflows/playwright.yml

name: Playwright Tests

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2- name: Set up Pythonuses: actions/setup-python@v2with:python-version: '3.8'- name: Install dependenciesrun: |python -m pip install --upgrade pippip install -r requirements.txtpip install pytest-playwright- name: Install browsersrun: playwright install- name: Run testsrun: pytest tests/ --html=report.html --self-contained-html- name: Upload test resultsuses: actions/upload-artifact@v2with:name: playwright-reportpath: report.html

第六部分:故障排除与调试

6.1 常见问题解决

troubleshooting.py

from playwright.sync_api import TimeoutError as PlaywrightTimeoutError

def robust_element_interaction(page, selector, max_attempts=3):
“”“健壮的元素交互”“”
for attempt in range(max_attempts):
try:
element = page.locator(selector)
element.wait_for(state=‘visible’, timeout=5000)
return element
except PlaywrightTimeoutError:
if attempt == max_attempts - 1:
raise
print(f"重试 {selector},尝试 {attempt + 1}/{max_attempts}")
page.wait_for_timeout(1000)

def handle_dynamic_content(page):
“”“处理动态内容”“”
# 等待特定条件
page.wait_for_function(“”"
() => {
const element = document.querySelector(‘.dynamic-content’);
return element && element.offsetHeight > 0;
}
“”")

# 重试机制
def retry_operation(operation, max_retries=3):for i in range(max_retries):try:return operation()except Exception as e:if i == max_retries - 1:raise epage.wait_for_timeout(1000)

def debug_script(script_path):
“”“调试脚本”“”
import pdb
from importlib import import_module
import sys

# 动态加载并调试脚本
sys.path.append('.')
spec = import_module(script_path.replace('.py', '').replace('/', '.'))
pdb.run('spec.main()')

总结

通过本指南,您已经全面掌握了使用Playwright生成Python自动化脚本的技能。从基础的环境搭建到高级的测试框架集成,从简单的页面录制到复杂的性能监控,Playwright为现代Web自动化测试提供了完整的解决方案。

关键要点:

  1. 录制是起点:代码生成器是快速入门的利器
  2. API是核心:深入理解Playwright API是精通的关键
  3. 模式很重要:页面对象模式提高代码可维护性
  4. 集成是生产力:与pytest等框架集成提升测试效率
  5. 监控保障质量:性能监控和错误处理确保测试可靠性

Playwright正在快速发展,建议持续关注官方文档和社区更新,以掌握最新的特性和最佳实践。

http://www.dtcms.com/a/462623.html

相关文章:

  • maven本地仓库有相应的依赖,依旧会从远程仓库拉取问题的原因及解决
  • 如何修改wordpress站景区旅游网站平台建设方案
  • 网站建设拾金手指下拉十九济南天桥区做网站的
  • 甘肃水利工程建设管理网站东省住房和城乡建设厅网站
  • 10.9 换根dp
  • 上海做网站设计温州专业微网站制作多少钱
  • Trino:一个开源分布式大数据SQL查询引擎
  • 网站建设岗位职责做网站能致富吗
  • 网站优化方案设计wordpress删除用户头像
  • C# 弃元模式:从语法糖到性能利器的深度解析
  • 外国优秀网站欣赏广东茂名网站建设
  • 网站备案的用户名是什么广州比较好的网站建设
  • INT301 Bio-computation 生物计算(神经网络)Pt.1 导论与Hebb学习规则
  • 百度站长平台男女做暖暖的网站大全
  • 乌克兰集团网站建设wordpress 产品目录
  • C#基础16-C#6-C#9新特性
  • 两个RNA-蛋白以及蛋白间相互作用数据库
  • 《低速园区场景下决策模块的成本函数设计与编程实践》
  • 网站推广方法是什么企业网站建设cms系统
  • SpringBoot 集成 LangChain4j 本地调用 Ollama
  • 大前端最新网站设计一个企业官网的栏目
  • Vue 菜单权限管理的计与实现
  • 怎么自己做网站共享办公室 设计
  • Linux进程第八讲——进程状态全景解析(二):从阻塞到消亡的完整生命周期
  • 网站设计审美角度公司手机网站建设
  • 【数据结构】优先级队列(堆)
  • 合肥网站建设首选 晨飞网络nas的wordpress的端口
  • 动漫网站开发优势网店交易哪个平台好
  • Python 中的集合(set)知识大全
  • 网站开发工具的功能包括现在的公司都有自己的网站吗