
playwright 官方文档:https://playwright.dev/python/docs/intro#installing-playwright-pytest
playwright官方提供了 pytest-playwright 包,支持通过 python 语言写前端自动化
下面来搭建前端 UI 自动化测试框架,需要考虑项目结构、配置文件、测试用例编写、运行方式等部分
一个规范的框架结构应便于维护测试用例、配置、公共方法等,推荐结构如下:
playwright_ui_auto/
├── config/ # 配置文件目录
│ ├── env.py # 环境配置(如测试/生产环境 URL)
│ └── settings.py # 框架全局设置(如超时时间、截图路径等)
├── tests/ # 测试用例目录(pytest 默认识别该目录)
│ ├── conftest.py # pytest 夹具(fixture)配置(公共资源)
│ ├── test_login.py # 登录模块测试用例
│ └── test_search.py # 搜索模块测试用例
├── common/ # 公共工具类目录
│ ├── page_base.py # 页面基类(封装通用操作:点击、输入等)
│ └── logger.py # 日志工具
├── reports/ # 测试报告目录(自动生成)
├── screenshots/ # 截图目录(失败时自动保存)
├── pytest.ini # pytest 配置文件(指定参数、插件等)
└── requirements.txt # 项目依赖清单(可选,用于环境复刻)
用于指定测试目录、默认命令行参数、报告格式等,示例:
[pytest]
testpaths = tests # 测试用例存放目录
pythonpath = . # 项目根目录加入环境变量(避免导入模块报错)
addopts = -vs --html=reports/report.html # 运行时默认参数:-vs 显示详细日志,生成 HTML 报告
markers =
smoke: 冒烟测试用例 # 标记用例(如 @pytest.mark.smoke)
login: 登录模块测试
管理不同环境的 URL,避免硬编码到测试用例:
# 环境配置:开发/测试/生产环境的基础 URL
ENV_CONFIG = {
"dev": "https://dev.example.com",
"test": "https://test.example.com",
"prod": "https://example.com"
}
# 默认使用测试环境
DEFAULT_ENV = "test"
BASE_URL = ENV_CONFIG[DEFAULT_ENV]
利用 pytest 的 fixture 机制,封装公共资源(如浏览器实例、页面实例),避免重复初始化:
import pytest
from playwright.sync import Page, Browser
from config.env import BASE_URL
# 定义浏览器夹具(scope="session" 表示整个测试会话只启动一次浏览器)
@pytest.fixture(scope="session")
def browser(playwright):
# 启动浏览器(headless=False 表示显示浏览器窗口,便于调试)
browser = playwright.chromium.launch(headless=False)
yield browser
browser.close() # 测试结束后关闭浏览器
# 定义页面夹具(每个测试用例前打开新页面)
@pytest.fixture(scope="function")
def page(browser: Browser):
page = browser.new_page()
page.goto(BASE_URL) # 打开默认环境的 URL
yield page
page.close() # 测试结束后关闭页面
fixture(翻译为 固定装置、夹具)的含义:指在测试执行前设置的环境或状态,以确保测试能够在一致和可控的条件下进行
用于:1 测试环境的准备;2 测试数据的设置;3 清理工作
文档:https://playwright.dev/python/docs/writing-tests
测试文件名、函数名都需要以 test_ 为前缀
示例:test_example.py
import re
from playwright.sync_api import Page, expect
def test_has_title(page: Page):
page.goto("https://playwright.dev/")
# Expect a title "to contain" a substring.
expect(page).to_have_title(re.compile("Playwright"))
def test_get_started_link(page: Page):
page.goto("https://playwright.dev/")
# Click the get started link.
page.get_by_role("link", name="Get started").click()
# Expects page to have a heading with the name of Installation.
expect(page.get_by_role("heading", name="Installation")).to_be_visible()
大多数测试从导航到页面的 URL 开始,然后与页面的元素进行交互
page.goto(“https://playwright.dev/”)
Playwright 回等待页面加载完成后再继续操作
playwright 使用 locators API 来实现定位元素
Playwright 会自动等待元素可操作后再执行操作,因此无需显式的等待元素可用。
locators API:https://playwright.dev/python/docs/locators
示例:
# Create a locator.
get_started = page.get_by_role("link", name="Get started")
# Click it.
get_started.click()
# 写成一行
page.get_by_role("link", name="Get started").click()
常用定位函数:
| locator.check() | 勾选输入复选框 |
|---|---|
| locator.click() | 单击元素 |
| locator.uncheck() | 取消选中输入复选框 |
| locator.hover() | 将鼠标悬停在元素上 |
| locator.fill() | 填写表单字段,输入文本 |
| locator.focus() | 聚焦元素 |
| locator.press() | 按单个键 |
| locator.set_input_files() | 上传文件 |
| locator.select_option() | 在下拉菜单中选择选项 |
Playwright 包含一些断言,这些断言会等到预期条件满足后再执行。使用这些断言可以使测试更加稳定且更具弹性。例如,以下代码将等到页面获取到包含“Playwright”的标题
import re
from playwright.sync_api import expect
expect(page).to_have_title(re.compile("Playwright"))
断言API:https://playwright.dev/python/docs/test-assertions
常用断言函数
| expect(locator).to_be_checked() | 复选框已选中 |
|---|---|
| expect(locator).to_be_enabled() | 控制已启用 |
| expect(locator).to_be_visible() | 元素可见 |
| expect(locator).to_contain_text() | 元素包含文本 |
| expect(locator).to_have_attribute() | 元素具有属性 |
| expect(locator).to_have_count() | 元素列表已指定长度 |
| expect(locator).to_have_text() | 元素匹配文本 |
| expect(locator).to_have_value() | 输入元素有值 |
| expect(page).to_have_title() | 页面有标题 |
| expect(page).to_have_url() | 页面有 url |
使用 Playwright 编写的测试在浏览器上下文的隔离干净环境中执行。这种隔离模型提高了可重复性,并防止了级联测试失败。
playwright pytest 插件基于 测试fixture 的概念
测试隔离是指每个测试与其他测试完全隔离。每个测试都独立运行。这意味着每个测试都有自己的本地存储、会话存储、Cookie 等。Playwright 使用 BrowserContext 来实现这一点,这些 BrowserContext 相当于类似隐身模式的配置文件。它们创建速度快、成本低,并且完全隔离,即使在单个浏览器中运行也是如此。Playwright 为每个测试创建一个上下文,并在该上下文中提供一个默认页面 。
如下面的两个测试函数也是环境隔离的,每个page都是独立的
from playwright.sync_api import Page
def test_example_test(page: Page):
pass
# “page” 属于一个独立的浏览器上下文,用于指定的测试
def test_another_test(page: Page):
pass
# 第二个 page 完全独立于第一个 page
测试隔离官方说明:https://playwright.dev/python/docs/browser-contexts
fixture 用于在测试之前或之后执行代码,并在测试之间共享对象,就是安排好各个步骤和数据,是测试完成任务的基础。
如果想使得所有测试都以来的fixture(固定装置),autouse fixtures 提供了此功能
autouse fixtures:https://docs.pytest.org/en/6.2.x/fixture.html#autouse-fixtures-fixtures-you-don-t-have-to-request
我们可以通过将 autouse=True 传递给 Fixture 的装饰器,使 Fixture 成为自动使用 Fixture。以下是一个简单的使用示例,其中 append_first 是一个autouse fixture,因此即使在两个测试函数中没有显式调用,也会自动被调用
# contents of test_append.py
import pytest
@pytest.fixture
def first_entry():
return "a"
@pytest.fixture
def order(first_entry):
return []
@pytest.fixture(autouse=True)
def append_first(order, first_entry):
return order.append(first_entry)
def test_string_only(order, first_entry):
assert order == [first_entry]
def test_string_and_int(order, first_entry):
order.append(2)
assert order == [first_entry, 2]
Playwright 具有开箱即用生成测试的功能,是快速开始测试的绝佳方式。它会打开两个窗口:一个浏览器窗口,您可以在其中与要测试的网站进行交互;另一个是 Playwright 检查器窗口,您可以在其中记录测试、复制测试、清除测试以及更改测试语言。
测试生成器:https://playwright.dev/python/docs/codegen
额外参数:请参考上面的文档
使用 --device 选项模拟移动设备时记录脚本和测试,该选项设置视口大小和用户代理等。
使用 --color-scheme 选项模拟配色方案时记录脚本和测试。
使用 --timezone 、 --geolocation 和 --lang 选项模拟时区、语言和位置,录制脚本和测试
使用 --save-storage 运行 codegen 以在会话结束时保存 cookies 、 localStorage 和 IndexedDB 数据
等。。。
运行 codegen 命令启动用例生成器,参数为URL,可选
playwright codegen [url]
会自动打开浏览器指定网页,并打开一个操作录制器
在浏览器中操作后,录制器会记录下操作并自动生成对应交互代码


1 拖拽功能条
2 开始/暂停录制
3 pick locator:元素定位,会自动定位元素
4 assert visibility:断言元素可见
5 assert text:断言元素包含特定文本
6 assert value:断言元素具有特定值
7 assert snapshot:断言元素具有指定快照

:复制当前代码框中生成的代码
:clear,清楚代码并重新开始录制
target:生成的代码语言,有python、java、nodejs、json等
:录制器主题,夜间模式
当在浏览器中的所有操作完成后,检查生成的代码,并自行粘贴到自己的代码中,然后关闭即可(不会自动保存)
参考:https://playwright.dev/python/docs/running-tests
运行(无头模式,即不打开任何浏览器窗口,结果显示在终端):pytest [测试文件…]
参数:https://playwright.dev/python/docs/test-runners
–head,测试时会打开浏览器窗口
–browser [浏览器名称],指定浏览器运行测试
-k [测试函数名],运行特定的测试函数
–numprocesses [num],指定测试进程数,并行运行测试
调试:https://playwright.dev/python/docs/debug
bash:PWDEBUG=1 pytest -s [文件名…],打开playwright inspector进行调试
调试特定测试函数:
https://playwright.dev/python/docs/trace-viewer
Playwright Trace Viewer 是一个 GUI 工具,可让您探索测试的记录的 Playwright 跟踪,这意味着您可以前后移动测试的每个操作,并直观地查看每个操作期间发生的情况。
记录跟踪:pytest --tracing on
option:
off:默认,不打开跟踪
on:打开跟踪
retain-on-failure:删除成功的测试用例的跟踪,只保留失败的
跟踪记录根据文档所述,存放在 test-results/ 目录下的trace.zip
我咋没找到嘞
打开跟踪记录
方式一:终端打开:playwright show-trace trace.zip
方式二:浏览器访问:trace.playwright.dev
从本质上讲,测试的本质是行动和断言
根据 pytest 给出的描述,https://docs.pytest.org/en/6.2.x/fixture.html#autouse-fixtures-fixtures-you-don-t-have-to-request
测试分为四个步骤:
arrange(统筹安排)
act(行为动作)
assert(断言)
cleanup(清理)
首先为测试做好一切的准备,这几乎涵盖了除了 “Act” 之外的所有步骤。它就像排列多米诺骨牌,以便动作能够在一个状态改变的步骤中完成。这可能意味着准备对象、启动/终止服务、将记录录入数据库,甚至包括定义要查询的 URL、为尚不存在的用户生成凭证,或者只是等待某个进程完成。
想要测试的某个动作,可能会产生状态的变化,观察以及通过断言来判断行为获得结果,行为通常定义为函数
断言,观察 Act 的最终状态,并检查是否符合预期。
测试的收尾工作,以确保其他测试不会受影响