Python之Playwright+AI UI自动化测试框架搭建与实战

Playwright是一个强大的Python库,仅用一个API即可自动执行ChromiumFirefoxWebKit等主流浏览器自动化操作,并同时支持以无头模式、有头模式运行。

Playwright提供的自动化技术是绿色的、功能强大、可靠且快速,支持LinuxMac以及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)不同场景启动命令:

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(替换为实际代理地址)。

四、功能录制操作

  1. 执行上述 "Playwright 启动命令" 后,会自动打开两个窗口:一个是目标浏览器(加载bbi-cloud-sit.baozun.com),一个是 "Playwright Recorder"(录制控制面板)。
  2. 在浏览器中操作目标网站的测试功能(如登录、点击按钮、输入文本、提交表单等),录制面板会实时生成对应的 Python 代码。
  3. 操作完成后,点击录制面板的 "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(打开即可查看可视化测试报告)。

相关推荐
KG_LLM图谱增强大模型2 小时前
OpenClaw官方解密:开源AI Agent 智能体平台的蜕变之路
人工智能·开源
TEC_INO2 小时前
Linux41:OPENCV图形计算面积、弧长API讲解
人工智能·opencv·计算机视觉
香草泡芙2 小时前
解锁AI Agent潜能:基于Langchain组件库的落地指南(1)
人工智能
chushiyunen2 小时前
pycharm打包whl
人工智能·pytorch·python
墨染天姬2 小时前
【AI】PyTorch 框架
人工智能·pytorch·python
jeffsonfu2 小时前
学习率调度的艺术:从Warmup到余弦退火,掌握深度学习的训练节奏
人工智能·深度学习·神经网络
大强同学2 小时前
Obsidian 视觉化技能包
人工智能·ai编程
AI+程序员在路上2 小时前
在pyCharm 中命令打包生成exe文件方法
ide·python·pycharm
chaors2 小时前
Langchain入门到精通0x08:摘要链(load_summarize_chain)
人工智能·langchain·ai编程