Pytest与Playwright自动化测试环境搭建与框架设计实战指南
1. 项目概述为什么选择 Pytest Playwright 这套组合拳如果你正在寻找一套能打、稳定、且面向未来的 UI 自动化测试方案那么Pytest加Playwright的组合绝对值得你投入时间深入研究。我接触过 Selenium、Cypress 等一众工具最终在团队的新项目中全面转向了这套技术栈原因很简单它解决了传统 UI 自动化中几个最让人头疼的痛点。首先Playwright 的“稳”是出了名的。它由微软团队开发原生支持 Chromium、Firefox 和 WebKit 三大浏览器引擎这意味着你的脚本在 Chrome、Edge、Safari 上都能获得高度一致的执行效果。更关键的是它内置了智能等待机制能自动等待元素可操作、网络请求完成大大减少了因页面加载或异步操作导致的“元素找不到”的随机失败。其次Pytest 的“强”在于其强大的测试组织能力和丰富的插件生态。用 Pytest 来组织你的 UI 测试用例就像用专业的乐高积木搭建城堡夹具Fixture管理测试前后的资源如浏览器实例参数化轻松实现数据驱动丰富的断言方式让结果验证更直观再加上 Allure 等插件生成美观的报告整个测试流程的专业度和可维护性直接上了一个台阶。这个系列的第二篇我们就来扎扎实实地搞定环境搭建和基础框架的雏形。我会带你一步步安装所有必需的工具并搭建一个清晰、可扩展的目录结构。这个基础打好了后续编写用例、管理页面对象、生成报告都会事半功倍。无论你是刚接触 UI 自动化的新手还是从其他框架如 Selenium unittest迁移过来的老手跟着这篇指南走都能快速上手。2. 核心工具安装与环境配置详解工欲善其事必先利其器。搭建环境看似简单但细节决定成败。一个干净、隔离且版本匹配的 Python 环境是避免后续各种诡异依赖冲突的前提。我会分步讲解并解释每一步背后的原因。2.1 Python 环境与包管理工具准备我强烈建议使用Conda或venv来创建独立的虚拟环境。这能确保你的项目依赖不会污染系统级的 Python 包也方便在不同项目间切换。这里以venv为例因为它轻量且是 Python 3 自带的。# 1. 创建项目目录并进入 mkdir playwright-ui-automation cd playwright-ui-automation # 2. 创建虚拟环境假设你的 Python 3 命令是 python3 python3 -m venv venv # 3. 激活虚拟环境 # 在 Windows 上 venv\Scripts\activate # 在 macOS/Linux 上 source venv/bin/activate激活后你的命令行提示符前通常会显示(venv)表示你已进入该虚拟环境。后续所有pip install操作都只影响这个环境。注意有些系统尤其是 Windows在安装 Python 时可能没有将python和pip命令添加到系统路径或者存在多个 Python 版本。如果遇到python命令未找到可以尝试使用py -3或python3。确认版本可以用python --version。我个人的习惯是始终使用python -m pip来代替直接的pip命令这样可以精确指定使用当前 Python 解释器下的 pip避免混淆。2.2 核心依赖包安装Pytest 与 Playwright接下来安装两位主角。我们将使用pip进行安装。为了确保版本兼容性和可复现性最好将依赖记录在requirements.txt文件中。首先直接安装pip install pytest playwright安装playwright包的同时它会包含核心的 Python 客户端库。但请注意这还没有安装实际的浏览器运行时。这是 Playwright 设计上的一个特点将客户端库和浏览器二进制文件分离管理。安装完成后你需要安装 Playwright 所需的浏览器。这是至关重要的一步。playwright install这条命令会下载 Chromium、Firefox 和 WebKit 的预备版本。这些浏览器是专门为 Playwright 优化过的并非你系统上安装的普通 Chrome 或 Firefox。下载可能会花费一些时间取决于你的网络速度。实操心得playwright install默认会安装所有三个浏览器。如果你的测试场景只针对 Chromium覆盖 Chrome 和 Edge可以指定安装以节省时间和磁盘空间playwright install chromium。另外如果遇到下载速度极慢或失败的情况这在某些网络环境下常见可以尝试设置环境变量来使用国内镜像例如在命令前添加PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/。我在公司内网就经常需要这样配置。2.3 验证安装与初步试运行安装完成后做个快速验证确保一切就绪。验证 Pytestpytest --version这应该会输出 Pytest 的版本号例如pytest 8.x.x。验证 Playwright 创建一个简单的 Python 脚本test_verify.pyimport playwright.sync_api def test_browser_launch(): with playwright.sync_api.sync_playwright() as p: # 尝试启动 Chromium 浏览器 browser p.chromium.launch(headlessFalse) # headlessFalse 让我们能看到浏览器 page browser.new_page() page.goto(https://www.example.com) title page.title() print(fPage title: {title}) browser.close() assert Example in title在项目根目录下运行pytest test_verify.py -v如果一切正常你应该会看到一个浏览器窗口打开访问 example.com然后在控制台看到测试通过的信息。这证明了 Playwright 的浏览器驱动和 Python 绑定都工作正常。踩过的坑第一次运行时可能会报错提示缺少某些依赖库特别是在 Linux 系统上。例如Playwright 可能需要libenchant等库来处理字体。错误信息通常会明确告诉你需要安装什么包。在 Ubuntu/Debian 上你可能需要运行sudo apt-get install一系列开发库。请仔细阅读错误日志并根据 Playwright 官方文档的 系统依赖 部分进行安装。3. 项目目录结构与基础框架搭建一个清晰的目录结构是维护大型自动化测试项目的基石。它让代码组织有序职责分离新人也能快速上手。下面是我在多个项目中总结并优化后的一套结构你可以直接作为模板。playwright-ui-automation/ ├── requirements.txt # 项目依赖包列表 ├── pytest.ini # Pytest 配置文件 ├── conftest.py # Pytest 共享夹具Fixture定义 ├── common/ # 公共模块 │ ├── __init__.py │ ├── config.py # 配置文件读取环境、URL、账号等 │ ├── logger.py # 日志记录模块 │ └── utils.py # 通用工具函数如数据生成、文件操作 ├── pages/ # 页面对象模型Page Object目录 │ ├── __init__.py │ ├── base_page.py # 所有页面对象的基类 │ └── login_page.py # 示例登录页面对象 ├── tests/ # 测试用例目录 │ ├── __init__.py │ ├── test_login.py # 示例登录功能测试用例 │ └── test_search.py # 示例搜索功能测试用例 ├── fixtures/ # 自定义 Pytest 夹具可选复杂时可独立 │ └── browser_fixture.py ├── data/ # 测试数据文件JSON, YAML, CSV │ └── test_users.json ├── reports/ # 测试报告输出目录由插件生成 │ └── allure-results/ # Allure 原始结果 └── screenshots/ # 失败截图保存目录现在我们来逐一创建这些核心文件并填充基础内容。3.1 依赖管理文件requirements.txt在项目根目录创建requirements.txt记录精确的版本号有助于团队协作和环境复现。pytest8.0.0 playwright1.40.0 allure-pytest2.13.2 pytest-html4.1.1 pytest-xdist3.5.0 python-dotenv1.0.0pytest-html生成 HTML 格式的测试报告。allure-pytest集成 Allure 报告生成更美观、交互性更强的报告。pytest-xdist支持测试并行运行大幅提升执行速度。python-dotenv用于从.env文件加载环境变量管理敏感配置。安装所有依赖pip install -r requirements.txt3.2 Pytest 配置文件pytest.inipytest.ini文件用于配置 Pytest 的默认行为非常有用。[pytest] # 指定测试文件的位置和命名模式 testpaths tests python_files test_*.py python_classes Test* python_functions test_* # 添加命令行默认选项 addopts -v # 详细输出 --strict-markers # 严格检查标记 --htmlreports/pytest_report.html # 生成HTML报告 --self-contained-html # 生成独立的HTML文件 --alluredirreports/allure-results # 生成Allure结果数据 # 定义自定义标记markers用于分类运行测试 markers smoke: 冒烟测试用例 regression: 回归测试用例 login: 与登录相关的测试这个配置意味着你直接在项目根目录运行pytest命令时它会自动在tests/目录下查找以test_开头的文件并执行其中以Test开头的类里的test_开头的方法。同时会自动生成 HTML 和 Allure 报告。3.3 共享夹具定义conftest.pyconftest.py是 Pytest 的魔力所在其中定义的夹具Fixture可以被同一目录及子目录下的所有测试文件自动发现和使用。我们将在这里定义最核心的浏览器夹具。import pytest from playwright.sync_api import Page, BrowserContext, Browser, Playwright import logging # 配置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) pytest.fixture(scopesession) def playwright_instance() - Playwright: 在整个测试会话中只启动一次 Playwright 实例。 from playwright.sync_api import sync_playwright with sync_playwright() as playwright: logger.info(Playwright instance started.) yield playwright logger.info(Playwright instance closed.) pytest.fixture(scopefunction) # 默认是 function 级别每个测试函数一个浏览器上下文 def browser_context(playwright_instance: Playwright, request) - BrowserContext: 为每个测试函数创建一个浏览器上下文Context。 上下文相当于一个独立的浏览器会话隔离了 cookies、localStorage 等。 # 可以从命令行参数或标记中获取浏览器类型默认为 chromium browser_type getattr(request.config.option, browser, chromium) browser getattr(playwright_instance, browser_type) # 启动浏览器可配置 headless 模式 headless not request.config.getoption(--headed) # 默认无头加 --headed 参数则显示 browser_instance browser.launch(headlessheadless, args[--start-maximized]) # 创建上下文可以在此统一设置视口、用户代理、忽略 HTTPS 错误等 context browser_instance.new_context( viewport{width: 1920, height: 1080}, ignore_https_errorsTrue, # 忽略 HTTPS 证书错误用于测试环境 # record_video_dirvideos/ if request.config.getoption(--video) else None # 可选录制视频 ) # 在测试失败时自动截图并保存到上下文方便夹具在清理前获取 context._test_failed False def on_page(page): page.on(pageerror, lambda exception: logger.error(fPage error: {exception})) context.on(page, on_page) yield context # 测试结束后关闭上下文和浏览器 context.close() browser_instance.close() pytest.fixture(scopefunction) def page(browser_context: BrowserContext) - Page: 为每个测试函数创建一个新的页面Tab。 这是最常用的夹具测试用例直接使用这个 page 对象来操作。 page browser_context.new_page() yield page page.close() # 添加一个自定义命令行选项用于指定浏览器 def pytest_addoption(parser): parser.addoption( --browser, actionstore, defaultchromium, help指定浏览器: chromium, firefox 或 webkit ) parser.addoption( --headed, actionstore_true, defaultFalse, help以有头模式运行显示浏览器界面 ) parser.addoption( --video, actionstore_true, defaultFalse, help录制测试视频 )这个conftest.py做了几件关键事playwright_instance会话级夹具整个测试运行期间只初始化一次 Playwright效率高。browser_context函数级夹具为每个测试用例创建一个干净的浏览器上下文。这是实现测试隔离的关键确保用例之间 cookies、缓存不互相干扰。这里还集成了命令行参数可以动态选择浏览器和运行模式。page函数级夹具每个用例获得一个全新的页面对象。测试脚本主要与这个page交互。pytest_addoption添加了自定义命令行参数让运行测试时更灵活。注意事项夹具的scope作用域选择很重要。session级别效率最高但要注意资源清理。function级别隔离性最好但创建开销稍大。对于浏览器实例通常用session对于上下文和页面用function是更安全的选择。yield之前的代码是“设置”之后的代码是“清理”确保了资源即使测试失败也能被正确关闭。4. 编写第一个页面对象与测试用例有了稳固的基础设施我们来创建第一个页面对象和测试用例感受一下这套框架的流畅度。4.1 创建页面对象基类common/base_page.py页面对象模型Page Object Model POM的核心思想是将页面的元素定位和操作封装成类让测试用例更关注业务逻辑而非底层实现。一个设计良好的基类能减少大量重复代码。from playwright.sync_api import Page, Locator, expect import logging import time from typing import Tuple, Optional class BasePage: 所有页面对象的基类封装通用操作和等待逻辑。 def __init__(self, page: Page): self.page page self.logger logging.getLogger(self.__class__.__name__) self.timeout 30000 # 默认超时时间 30 秒 def navigate(self, url: str) - None: 导航到指定URL并等待页面加载到网络空闲状态。 self.logger.info(fNavigating to: {url}) self.page.goto(url, wait_untilnetworkidle) # wait_until 是关键参数 # 可以在这里添加额外的页面加载完成检查 def find_element(self, selector: str, timeout: Optional[int] None) - Locator: 查找单个元素并等待其可见。 timeout timeout or self.timeout self.logger.debug(fFinding element: {selector}) element self.page.locator(selector).first # .first 确保获取第一个匹配项 element.wait_for(statevisible, timeouttimeout) return element def click(self, selector: str, timeout: Optional[int] None) - None: 点击元素并等待点击操作完成。 element self.find_element(selector, timeout) self.logger.info(fClicking element: {selector}) element.click() # Playwright 的 click 本身会进行可操作性检查这里通常不需要额外等待 def fill(self, selector: str, text: str, timeout: Optional[int] None) - None: 在输入框内填充文本并清空原有内容。 element self.find_element(selector, timeout) self.logger.info(fFilling {text} into element: {selector}) element.fill(text) def get_text(self, selector: str, timeout: Optional[int] None) - str: 获取元素的内部文本。 element self.find_element(selector, timeout) text element.inner_text() self.logger.debug(fGot text {text} from element: {selector}) return text def wait_for_selector(self, selector: str, state: str visible, timeout: Optional[int] None) - Locator: 等待特定选择器的元素达到指定状态visible, hidden, attached, detached。 timeout timeout or self.timeout self.logger.debug(fWaiting for selector {selector} to be {state}) return self.page.locator(selector).first.wait_for(statestate, timeouttimeout) def take_screenshot(self, name: str None) - None: 截取当前页面全屏截图用于调试或报告。 if name is None: name fscreenshot_{int(time.time())}.png path fscreenshots/{name} self.page.screenshot(pathpath, full_pageTrue) self.logger.info(fScreenshot saved to: {path}) def assert_element_visible(self, selector: str, timeout: Optional[int] None) - None: 使用 Playwright 的 expect 断言元素可见集成更友好的错误信息。 timeout timeout or self.timeout locator self.page.locator(selector).first expect(locator).to_be_visible(timeouttimeout)这个基类提供了最常用的方法。注意wait_untilnetworkidle和wait_for(statevisible)的使用它们是 Playwright 稳定性的保障。expect断言提供了比普通assert更丰富的等待和错误信息。4.2 实现具体页面对象pages/login_page.py以登录页面为例展示如何继承基类。from .base_page import BasePage class LoginPage(BasePage): 登录页面对象封装登录相关的所有元素和操作。 # 元素定位器Selector集中管理便于维护 USERNAME_INPUT #username PASSWORD_INPUT #password LOGIN_BUTTON button[typesubmit] ERROR_MESSAGE .alert-error SUCCESS_MESSAGE .welcome-message def __init__(self, page): super().__init__(page) self.url /login # 相对于基础URL的路径 def load(self, base_url: str) - None: 加载登录页面。 full_url f{base_url}{self.url} self.navigate(full_url) self.page.wait_for_url(f**{self.url}) # 等待URL跳转完成 def login(self, username: str, password: str) - None: 执行登录操作。 self.logger.info(fAttempting login with user: {username}) self.fill(self.USERNAME_INPUT, username) self.fill(self.PASSWORD_INPUT, password) self.click(self.LOGIN_BUTTON) # 可以在这里添加登录后的通用等待比如等待页面跳转或某个元素出现 def get_error_message(self) - str: 获取登录错误提示信息。 return self.get_text(self.ERROR_MESSAGE) def is_login_successful(self) - bool: 判断登录是否成功通过检查成功元素是否存在。 try: # 快速检查元素是否存在且可见不等待太久 self.wait_for_selector(self.SUCCESS_MESSAGE, timeout5000) return True except Exception: return False4.3 编写第一个测试用例tests/test_login.py现在使用我们创建的夹具和页面对象来编写测试。import pytest from pages.login_page import LoginPage from common.config import Config # 假设我们有一个配置模块 class TestLogin: 登录功能测试集。 pytest.fixture(autouseTrue) def setup(self, page): 每个测试方法执行前的准备工作。 self.page page self.config Config() # 读取配置 self.login_page LoginPage(page) self.login_page.load(self.config.base_url) def test_successful_login(self): 测试使用正确凭据登录成功。 # 从配置或数据文件读取测试数据 username self.config.valid_username password self.config.valid_password self.login_page.login(username, password) # 使用基类的断言方法 self.login_page.assert_element_visible(LoginPage.SUCCESS_MESSAGE) # 或者使用 Playwright 的 expect 直接断言 # from playwright.sync_api import expect # expect(self.page.locator(LoginPage.SUCCESS_MESSAGE)).to_be_visible() # 也可以断言 URL 跳转 # expect(self.page).to_have_url(**/dashboard) pytest.mark.parametrize(username, password, expected_error, [ (wrong_user, admin123, Invalid username or password), (admin, wrong_pass, Invalid username or password), (, admin123, Username is required), (admin, , Password is required), ]) def test_failed_login(self, username, password, expected_error): 参数化测试测试各种错误的登录凭据。 self.login_page.login(username, password) # 断言出现了错误提示并且提示信息正确 actual_error self.login_page.get_error_message() assert expected_error in actual_error, fExpected error {expected_error} not found in {actual_error} pytest.mark.smoke # 使用自定义标记可以通过 pytest -m smoke 只运行冒烟测试 def test_login_page_elements(self): 冒烟测试验证登录页面关键元素存在。 self.login_page.assert_element_visible(LoginPage.USERNAME_INPUT) self.login_page.assert_element_visible(LoginPage.PASSWORD_INPUT) self.login_page.assert_element_visible(LoginPage.LOGIN_BUTTON)这个测试类展示了几个关键点使用autouseTrue的夹具setup方法在每个测试方法前自动运行初始化页面对象。数据驱动测试使用pytest.mark.parametrize装饰器用多组数据运行同一个测试逻辑非常高效。标记Markers使用pytest.mark.smoke给测试打标签方便分类运行。清晰的断言使用封装好的断言方法或 Playwright 原生的expect使测试意图明确。5. 运行测试与报告生成框架搭建好了用例也写了现在是验收成果的时候。我们将学习如何运行测试并生成直观的报告。5.1 运行测试的多种方式在项目根目录下打开终端确保虚拟环境已激活你可以尝试以下命令运行所有测试pytest这会按照pytest.ini的配置运行tests/目录下所有测试。运行特定测试文件或类pytest tests/test_login.py # 运行单个文件 pytest tests/test_login.py::TestLogin # 运行单个测试类 pytest tests/test_login.py::TestLogin::test_successful_login # 运行单个测试方法使用标记运行pytest -m smoke # 只运行标记为 smoke 的测试 pytest -m not smoke # 运行除了 smoke 之外的所有测试并行运行测试利用 pytest-xdistpytest -n auto # 自动检测 CPU 核心数并行运行 pytest -n 2 # 指定 2 个 worker 并行运行并行能极大缩短测试套件的总执行时间特别适合用例多的场景。带界面运行调试时非常有用pytest --headed # 以有头模式运行你会看到浏览器窗口弹出 pytest --browserfirefox --headed # 指定用 Firefox 浏览器并显示界面5.2 生成与查看测试报告测试结果不能只看控制台一份美观的报告对于结果分析、历史追溯和团队分享至关重要。1. HTML 报告pytest-html我们已经配置了pytest.ini每次运行pytest都会在reports/目录下生成一个pytest_report.html文件。直接用浏览器打开这个文件可以看到一个包含通过率、失败用例、执行时长等信息的静态 HTML 报告。虽然简单但足够清晰。2. Allure 报告更推荐Allure 报告功能强大交互性好能展示测试步骤、截图、附件等。生成 Allure 结果数据运行测试时--alluredirreports/allure-results参数已经帮我们生成了原始数据一堆.json文件。生成并打开 Allure 报告首先你需要安装 Allure 命令行工具。可以参考 Allure 官方安装指南 。安装后运行allure generate reports/allure-results -o reports/allure-report --clean allure open reports/allure-report第一条命令根据结果数据生成可浏览的 HTML 报告。第二条命令会在你的默认浏览器中打开这份报告。Allure 报告里你可以看到清晰的用例层级、通过/失败状态、每个测试步骤的详细日志如果使用了allure.attach或 Pytest 的caplog夹具、以及我们在夹具或用例中自动附加的截图需要在conftest.py或用例中实现截图逻辑并附加到 Allure。这是向非技术人员展示测试结果的最佳方式。实操心得为了在 Allure 报告中自动附加失败用例的截图可以在conftest.py的browser_context或page夹具中添加逻辑。一种常见做法是使用 Pytest 的pytest_runtest_makereport钩子函数在测试失败时获取当前的page对象并截图然后使用allure.attach将图片附加到报告中。这需要一些额外的配置但一旦设置好调试失败用例时会非常方便。6. 常见问题与排查技巧实录在实际搭建和运行过程中你肯定会遇到各种各样的问题。这里我总结了一些高频问题和解决方法。6.1 安装与环境问题问题1playwright install下载浏览器极慢或失败。原因Playwright 默认从 Google 的存储库下载浏览器国内网络可能访问不畅。解决使用环境变量指定镜像源推荐# Linux/macOS export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/ playwright install # Windows (PowerShell) $env:PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/ playwright install使用--with-deps参数并手动设置 npm 镜像如果上述方法不行npm config set registry https://registry.npmmirror.com/ playwright install --with-deps chromium问题2运行时报错关于GLIBCXX或libxxx找不到。原因系统缺少 Playwright 浏览器运行所需的底层动态库。解决根据错误信息安装对应的系统包。在 Ubuntu/Debian 上通常需要sudo apt-get update sudo apt-get install -y libnss3 libatk-bridge2.0-0 libdrm-dev libxkbcommon-dev libgbm-dev libasound-dev libpangocairo-1.0-0 libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxi6 libxtst6 libxrandr2 libgtk-3-0 libxss1请始终以 Playwright 官方文档的系统要求章节为准。6.2 元素定位与等待问题问题3测试不稳定有时找不到元素TimeoutError。原因这是 UI 自动化最常见的问题。页面加载速度、网络请求、动态渲染都可能导致元素出现时机不确定。解决优先使用 Playwright 的自动等待page.click(),page.fill(),locator.click()等方法内部已经包含了等待元素可操作可见、启用、稳定的逻辑。尽量避免使用time.sleep()。使用明确的等待page.wait_for_selector(),locator.wait_for()。wait_for_selector的state参数很实用visible,hidden,attached。等待网络请求page.goto(url, wait_untilnetworkidle)或page.wait_for_load_state(networkidle)。检查选择器使用浏览器开发者工具F12的 Playwright 插件或playwright codegen命令来生成可靠的选择器。确保选择器能唯一标识目标元素。问题4如何定位动态生成的元素如ID是随机字符串解决使用其他稳定属性如># CSS 选择器属性以...开头 page.locator([data-id^user-]) # XPath包含特定文本 page.locator(xpath//button[contains(text(), Submit)])使用 Playwright 的get_by_*系列方法这是 Playwright 非常强大的特性语义清晰抗动态变化能力强。page.get_by_role(button, nameSign in) # 通过角色和可访问名 page.get_by_text(Click me) # 通过文本 page.get_by_placeholder(Enter your email) # 通过占位符 page.get_by_test_id(login-submit) # 通过>import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的变量到环境变量 class Config: def __init__(self): self.base_url os.getenv(BASE_URL, https://default.example.com) self.valid_username os.getenv(TEST_USERNAME, admin) self.valid_password os.getenv(TEST_PASSWORD, admin123)在测试中通过Config类获取配置。可以为不同环境创建不同的.env文件如.env.test,.env.staging在运行测试前通过环境变量指定加载哪个。问题7Allure 报告中没有截图或日志。解决需要主动将附件添加到 Allure。在conftest.py中实现一个钩子import allure import pytest pytest.hookimpl(tryfirstTrue, hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.when call and report.failed: # 假设 page 夹具在测试项中可用 page item.funcargs.get(page) if page: # 截图并附加到 Allure 报告 screenshot page.screenshot(full_pageTrue) allure.attach(screenshot, name失败截图, attachment_typeallure.attachment_type.PNG) # 也可以附加页面源代码 html page.content() allure.attach(html, name页面源码, attachment_typeallure.attachment_type.HTML)这段代码会在测试调用call阶段失败时尝试获取当前测试用例的page对象进行截图和获取源码并附加到 Allure 报告中。搭建过程就像盖房子地基环境与目录打得牢主体结构POM 与夹具设计得好后续的“装修”编写更多页面对象和用例和“入住”集成到 CI/CD才会顺畅。这套Pytest Playwright的组合提供了从编写、运行到报告的全套现代化解决方案其稳定性和开发体验远超许多传统方案。当你熟悉了这套流程后你会发现编写 UI 自动化测试不再是令人畏惧的苦差事而是一种高效、可靠的保障手段。

相关新闻

Selenium自动化中高效定位与操作span元素的实战指南

Selenium自动化中高效定位与操作span元素的实战指南

1. 项目概述:为什么span元素是Selenium自动化中的“硬骨头”?如果你用过Selenium做过网页自动化,无论是测试还是爬虫,肯定遇到过这样的场景:一个按钮,你明明看着它就在那里,用ID、用Class去定位…

2026/7/7 20:45:08阅读更多 →
豆包智能体下线完整说明 + 你的智能体抢救方案(附AI导出鸭批量备份实操)

豆包智能体下线完整说明 + 你的智能体抢救方案(附AI导出鸭批量备份实操)

一、确认:豆包自建智能体确实要下线,不是谣传 近期很多朋友在问“豆包智能体是不是要关了”,我在这里统一回复:是的,官方已发布明确公告。 根据字节跳动官方通知,豆包APP内用户自定义智能体功能将于2026年7…

2026/7/7 20:45:08阅读更多 →
Playwright自动化测试:使用storageState持久化登录状态提升效率

Playwright自动化测试:使用storageState持久化登录状态提升效率

1. 项目概述:告别重复登录,让自动化测试飞起来做自动化测试的朋友,尤其是用Playwright的,估计都经历过这个场景:每次跑测试用例,第一件事就是吭哧吭哧地登录系统。输入账号、密码,点登录按钮&am…

2026/7/7 20:45:08阅读更多 →
AI绘画实战:零基础生成爆款小黑风格插画

AI绘画实战:零基础生成爆款小黑风格插画

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在 GitHub 上看到一套非常火的“小黑”风格插画,简约的线条、扁平化的设计和强烈的氛围感,让很多开发者爱…

2026/7/7 23:06:09阅读更多 →
终极指南:如何一键找回Chrome浏览器中所有保存的密码 [特殊字符]

终极指南:如何一键找回Chrome浏览器中所有保存的密码 [特殊字符]

终极指南:如何一键找回Chrome浏览器中所有保存的密码 🔑 【免费下载链接】chromepass Get all passwords stored by Chrome on WINDOWS. 项目地址: https://gitcode.com/gh_mirrors/chr/chromepass 你是否曾经遇到过这样的情况:换了一…

2026/7/7 23:06:09阅读更多 →
MiniMax Hub一站式AI开发平台实战:集成Claude Code、画布编辑与自动化管线

MiniMax Hub一站式AI开发平台实战:集成Claude Code、画布编辑与自动化管线

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在尝试将 AI 编程工具集成到日常开发流程中,发现市面上的产品要么功能单一,要么配置复杂,很难…

2026/7/7 23:06:09阅读更多 →
STM32与TB6593FNG直流电机驱动系统设计与优化

STM32与TB6593FNG直流电机驱动系统设计与优化

1. 项目背景与核心组件选型在工业自动化和消费电子领域,直流电机控制一直是关键的基础技术。TB6593FNG作为东芝半导体推出的全桥刷式直流电机驱动器,配合STM32F415ZG这款高性能ARM Cortex-M4微控制器,能够构建出响应迅速、控制精准的电机驱动…

2026/7/7 23:06:09阅读更多 →
OpenClaw Mac 安装指南:M芯片适配与安全部署实践

OpenClaw Mac 安装指南:M芯片适配与安全部署实践

1. OpenClaw 是什么?它和 Mac、M 芯片、Claude Code 的关系必须先厘清 很多人点开这个标题,第一反应是:“OpenClaw 是不是 Claude Code 的 Mac 版?”“是不是能直接在 M 系列芯片上跑通 Claude 的本地代码助手?”——…

2026/7/7 23:06:09阅读更多 →
STM32F746ZG与NBM7100A的低功耗协同方案解析

STM32F746ZG与NBM7100A的低功耗协同方案解析

1. 项目背景与核心挑战在物联网和便携式设备爆炸式增长的今天,如何延长电池供电设备的续航时间成为硬件工程师面临的关键挑战。特别是那些使用不可充电初级电池(如CR2032纽扣电池)的设备,电池更换成本高且不便。我曾参与过一个野外…

2026/7/7 23:01:08阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/7 4:43:43阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/7 2:56:31阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/7 1:03:28阅读更多 →
Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

1. 项目概述:Acunetix v24.8 高级版漏洞扫描器深度解析作为一名在网络安全领域摸爬滚打多年的老兵,我深知一款趁手的“兵器”对于安全测试工作意味着什么。今天要聊的,就是Web应用安全测试领域里一个响当当的名字——Acunetix。特别是其v24.8…

2026/7/7 0:02:41阅读更多 →
国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot) 🌐 演示地址:http://ruoyioffice.com | 📦 源码1GitHub:ruoyi-office | 📦 源码2GitCode:ruoyi-o…

2026/7/7 0:02:41阅读更多 →
CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS SSH连接故障排查:从基础检查到深度修复的完整指南引言当你尝试通过Xshell或其他SSH客户端连接CentOS服务器时,突然遭遇"Connection refused"或"Connection timed out"的错误提示,这种经历对任何运维人员或开发者来…

2026/7/7 0:02:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/7 5:11:21阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/7 5:11:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/7 5:11:21阅读更多 →