Playwright是一个强大的Python库,仅用一个API即可自动执行Chromium、Firefox、WebKit等主流浏览器自动化操作,并同时支持以无头模式、有头模式运行。
Playwright提供的自动化技术是绿色的、功能强大、可靠且快速,支持Linux、Mac以及Windows操作系统。
一. 系统要求
- Python版本:3.8+(推荐3.10+以获得最佳兼容性)
- 操作系统:Windows 10+/macOS 12+/Linux(Ubuntu 20.04+或Debian 11+)
- 浏览器支持:Chromium、Firefox、WebKit(Safari内核)
二. 安装步骤
安装核心库(推荐使用清华源加速)
pip install playwright
下载浏览器二进制文件(自动匹配系统环境)
安装 Playwright 库及配套的浏览器驱动(Chrome、Firefox、Safari),无需手动单独下载浏览器驱动。
playwright install 或者 python3 -m playwright install
安装pytest插件(可选,用于测试框架集成)
pip install pytest-playwright
常见问题排查
问题 1:执行****playwright install 提示 "浏览器驱动未找到"
- 问题表现:终端输出 "Could not find browser executable" 或 "Driver not found"。
- 解决方案:重新执行 playwright install,确保网络稳定(避免下载中断)。
- 单独安装特定浏览器驱动:如 playwright install safari(替换为 chromium/firefox)。
问题 2:安装后提示 "浏览器启动权限不足"
- 问题表现:macOS/Linux 执行命令时输出 "Permission denied"(权限拒绝)。
- 解决方案:macOS/Linux 赋予权限:执行 chmod +x /Users/xxx/Library/Caches/ms-playwright/chromium-xxx/.../Chromium(路径替换为报错中的实际路径)。
- Windows 关闭杀毒软件:将 Playwright 缓存目录(C:\Users\xxx\AppData\Local\ms-playwright)添加到杀毒软件信任区,避免拦截。
三.Playwright 启动与环境配置
1. 核心命令(PyCharm 终端操作)
1)打开 PyCharm 底部 "Terminal",确保已关联正确 Python 环境(通过python --version验证)
2)不同场景启动命令:
- 常规 Web 端录制:playwright codegen bbi-cloud-sit.baozun.com;
- 移动端(iPhone 13)录制:playwright codegen --device="iPhone 13" bbi-cloud-sit.baozun.com;
- 切换浏览器(Chrome):playwright codegen -b ff bbi-cloud-sit.baozun.com(cr=Chrome,ff=Firefox,sf=Safari)。
2. 命令说明
codegen:Playwright 的录制功能,自动生成 UI 操作对应的 Python 代码;
--device:指定模拟的设备型号(通过playwright show-devices查看所有支持设备);
-b:指定使用的浏览器。
3. 常见问题排查
问题 1:执行****playwright codegen 后浏览器闪退
- 问题表现:浏览器短暂打开后立即关闭,录制面板未弹出。
- 解决方案:匹配浏览器版本:执行 playwright install --force 强制重新安装与浏览器兼容的驱动。
- 关闭后台进程:Windows 打开 "任务管理器"、macOS 打开 "活动监视器",结束所有目标浏览器进程后重试。
- 提升权限:Windows 以管理员身份运行终端,macOS/Linux 在命令前加sudo(如 sudo playwright codegen ...)。
问题 2:访问****bbi-cloud-sit.baozun.com 提示 "无法连接"
- 问题表现:浏览器打开网址后显示 "网页无法访问""DNS 解析失败"。
- 解决方案:验证网址:手动在浏览器输入网址,检查是否拼写错误或网络故障。
- 关闭代理 / VPN:部分内网网址受代理影响,关闭后重新执行命令。
- 配置代理(如需):添加代理参数,如 playwright codegen --proxy-server="http://127.0.0.1:8888" bbi-cloud-sit.baozun.com(替换为实际代理地址)。
四、功能录制操作
- 执行上述 "Playwright 启动命令" 后,会自动打开两个窗口:一个是目标浏览器(加载bbi-cloud-sit.baozun.com),一个是 "Playwright Recorder"(录制控制面板)。
- 在浏览器中操作目标网站的测试功能(如登录、点击按钮、输入文本、提交表单等),录制面板会实时生成对应的 Python 代码。
- 操作完成后,点击录制面板的 "Stop"(停止)按钮,复制面板中的代码到 PyCharm 的.py文件中(如test_ui.py),完成基础脚本录制。
五、AI 辅助添加测试报告
借助 PyCharm 中的 Continue 插件,为录制的脚本添加测试报告功能。
操作步骤
方法一 :
1)在项目中导入如下报告模板文件:ui_page_auto.py
python
# -*- coding: utf-8 -*-
import os
import re
from playwright.sync_api import Playwright, sync_playwright, expect
import datetime
# 定义报告目录和文件路径(当前代码目录下的report 文件夹)
current_dir = os.path.dirname(os.path.abspath(__file__))
report_dir = os.path.join(current_dir, "report")
def generate_html_report(report_data):
html_content = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>UI 自动化测试报告</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
h1 {{ color: #333; }}
.success {{ color: green; }}
.failed {{ color: red; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
<h1>UI 自动化测试执行报告</h1>
<p><strong>执行时间:</strong> {report_data['start_time']} 至 {report_data['end_time']}</p>
<p><strong>状态:</strong> <span class="{report_data['status_class']}">{report_data['status']}</span></p>
<h2>执行详情</h2>
<table>
<tr>
<th>步骤</th>
<th>结果</th>
<th>时间</th>
</tr>
{''.join([f'<tr><td>{step["name"]}</td><td>{step["result"]}</td><td>{step["time"]}</td></tr>'
for step in report_data['steps']])}
</table>
{f'<h2 class="failed">错误信息</h2><p>{report_data["error"]}</p>' if report_data['error'] else ''}
</body>
</html>
"""
report_path = os.path.join(report_dir, "ui_automation_report.html")
os.makedirs(report_dir, exist_ok=True)
with open(report_path, "w", encoding="utf-8") as file:
file.write(html_content)
print(f"尊敬的主人,HTML 报告已生成:{report_path}")
def run(playwright: Playwright) -> None:
report_data = {
'start_time': None,
'end_time': None,
'status': '成功',
'status_class': 'success',
'steps': [],
'error': None
}
try:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
report_data['start_time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def log_step(name, action=None):
step_time = datetime.datetime.now().strftime("%H:%M:%S")
if action:
action()
report_data['steps'].append({
'name': name,
'result': '通过',
'time': step_time
})
log_step("访问登录页面", lambda: page.goto("https://www.test.com&lang=zh_CN"))
log_step("输入账号", lambda: (
page.get_by_role("textbox", name="请输入账号").click(),
page.get_by_role("textbox", name="请输入账号").fill("test")
))
log_step("输入密码", lambda: (
page.get_by_role("textbox", name="请输入密码").click(),
page.get_by_role("textbox", name="请输入密码").fill("*123456")
))
log_step("点击登录", lambda: page.get_by_role("button", name="立即登录").click())
log_step("选择test品牌", lambda: page.get_by_role("listitem", name="test", exact=True).click())
log_step("输入手机号", lambda: (
page.get_by_role("textbox", name="请输入").first.click(),
page.get_by_role("textbox", name="请输入").first.fill("10015029486")
))
log_step("点击搜索", lambda: page.get_by_role("button", name="搜 索").click())
# 等待搜索结果加载
page.wait_for_timeout(2000)
# 尝试多种方式点击详情
try:
log_step("点击详情", lambda: page.get_by_text("详情").first.click())
except Exception as detail_error:
try:
# 如果直接点击失败,尝试使用 locator 并等待元素可见
detail_button = page.locator("text=详情").first
detail_button.wait_for(state="visible", timeout=5000)
detail_button.click()
report_data['steps'].append({
'name': '点击详情(备用方式)',
'result': '通过',
'time': datetime.datetime.now().strftime("%H:%M:%S")
})
except Exception as e2:
# 截图查看当前页面状态
page.screenshot(path=os.path.join(report_dir, "before_detail_screenshot.png"))
raise Exception(
f"点击详情失败:{e2}\n已保存截图:{os.path.join(report_dir, 'before_detail_screenshot.png')}")
log_step("点击积分详情", lambda: page.get_by_role("tab", name="积分详情").click())
log_step("点击增加积分", lambda: page.get_by_role("button", name="增加积分").click())
log_step("输入增加积分数值", lambda: (
page.get_by_role("textbox", name="请输入").first.click(),
page.get_by_role("textbox", name="请输入").first.fill("100")
))
log_step("输入生效天数", lambda: (
page.locator("span").filter(has_text="客户获取后第 天生效").get_by_placeholder("请输入").click(),
page.locator("span").filter(has_text="客户获取后第 天生效").get_by_placeholder("请输入").fill("0")
))
log_step("选择调整类型", lambda: (
page.get_by_text("请选择").click(),
page.get_by_role("option", name="人工调整").click()
))
log_step("输入备注", lambda: (
page.get_by_role("textbox", name="请输入").nth(2).click(),
page.get_by_role("textbox", name="请输入").nth(2).fill("30")
))
log_step("确认增加积分", lambda: page.get_by_role("button", name="确 认").click())
log_step("点击减少积分", lambda: page.get_by_role("button", name="减少积分").click())
log_step("输入减少积分数值", lambda: (
page.get_by_role("textbox", name="请输入").click(),
page.get_by_role("textbox", name="请输入").fill("50")
))
log_step("选择减少积分调整类型", lambda: (
page.get_by_text("请选择").click(),
page.get_by_role("option", name="人工调整").click()
))
log_step("确认减少积分", lambda: page.get_by_role("button", name="确 认").click())
log_step("点击入会详情", lambda: page.get_by_role("tab", name="入会详情").click())
log_step("点击等级详情", lambda: page.get_by_role("tab", name="等级详情").click())
log_step("点击成长值详情", lambda: page.get_by_role("tab", name="成长值详情").click())
log_step("点击订单详情", lambda: page.get_by_role("tab", name="订单详情").click())
log_step("再次点击积分详情", lambda: page.get_by_role("tab", name="积分详情").click())
except Exception as e:
report_data['status'] = '失败'
report_data['status_class'] = 'failed'
report_data['error'] = str(e)
report_data['steps'].append({
'name': '执行出错',
'result': '失败',
'time': datetime.datetime.now().strftime("%H:%M:%S")
})
try:
os.makedirs(report_dir, exist_ok=True)
page.screenshot(path=os.path.join(report_dir, "error_screenshot.png"))
with open(os.path.join(report_dir, "error_page.html"), "w", encoding="utf-8") as f:
f.write(page.content())
print(f"错误截图已保存:{os.path.join(report_dir, 'error_screenshot.png')}")
except:
pass
finally:
report_data['end_time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if 'browser' in locals():
context.close()
browser.close()
generate_html_report(report_data)
with sync_playwright() as playwright:
run(playwright)
2)在continue插件中@这个模板文件,输入如下话语:根据@ui_page_auto.py文件格式,修改如下代码:(输入刚才录制的脚本)
3)新建一个py文件,将生成的代码粘贴进该文件即可执行使用。
playwright推荐的内置定位
page.get_by_text()通过文本内容定位。
page.get_by_label()通过关联标签的文本定位表单控件。
page.get_by_placeholder()按占位符定位输入。
page.get_by_title()通过标题属性定位元素。
page.get_by_role()通过显式和隐式可访问性属性进行定位。
page.get_by_alt_text()通过替代文本定位元素,通常是图像。
page.get_by_test_id()根据data-testid属性定位元素(可以配置其他属性)。
方法二:
1)先安装pytest-html库(生成报告依赖):在 PyCharm 终端输入pip install pytest-html。
2)打开录制好的脚本文件(如test_ui.py),将光标定位到脚本末尾,点击 PyCharm 右侧的 "Continue" 插件图标。
3)在插件输入框中输入提示词:"基于当前 Playwright 脚本,添加 pytest-html 测试报告功能,要求报告包含测试用例名称、执行结果、执行时间、错误信息(若有)"。
4)插件生成代码后,检查并调整(如补充测试用例类、pytest装饰器),最终脚本结构示例:
python
from playwright.sync_api import sync_playwright
import pytest
from pytest_html import HTMLReport
def test_ui():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("www.test.com")
# 其他操作代码...
browser.close()
if __name__ == "__main__":
pytest.main(["-v", "test_ui.py", "--html=test_report.html"])
5)运行脚本:在终端输入python test_ui.py,执行完成后会在当前目录生成test_report.html(打开即可查看可视化测试报告)。