news 2026/4/16 5:40:20

【自动化测试】 pytest 结合 Playwright 实现页面元素在两个区域间拖拽

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【自动化测试】 pytest 结合 Playwright 实现页面元素在两个区域间拖拽

pytest 结合 Playwright 实现页面元素在两个区域间拖拽

      • ✅ 示例场景
      • 1. 创建示例 HTML 页面 (`drag_drop_block.html`)
      • 2. Pytest + Playwright 测试代码 (`test_block_drag_drop.py`)
      • 3. 运行测试
    • 关联文档

好的,下面是使用pytest结合Playwright实现页面元素在两个区域间拖拽的完整示例。

这个示例将创建一个包含两个区域(sourcetarget)和一个可拖拽区块的 HTML 页面,然后使用 Playwright 模拟将该区块从一个区域拖拽到另一个区域的操作。

✅ 示例场景

我们将创建一个简单的 HTML 页面,包含:

  1. Source Area: 包含一个可拖拽的区块(例如一个带颜色的<div>)。
  2. Target Area: 一个空的区域,用于接收被拖拽的区块。
  3. JavaScript: 实现 HTML5 拖放 API,处理dragstart,dragover, 和drop事件,以便将元素从source移动到target

1. 创建示例 HTML 页面 (drag_drop_block.html)

将以下 HTML 代码保存为drag_drop_block.html文件。

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Block Drag & Drop Example</title><style>body{font-family:Arial,sans-serif;margin:40px;}.area{width:300px;height:200px;border:2px dashed #ccc;display:inline-block;vertical-align:top;margin:20px;padding:10px;position:relative;}#source-area{background-color:#e0f7fa;/* Light Blue */}#target-area{background-color:#f3e5f5;/* Light Purple */}.draggable-block{width:100px;height:100px;background-color:#f44336;/* Red */color:white;text-align:center;line-height:100px;/* Vertically center text */cursor:move;/* Show move cursor */user-select:none;/* Prevent text selection */position:absolute;/* Position within parent */top:30px;left:50px;}.block-content{font-size:12px;}/* Optional: Visual feedback during drag */.draggable-block.dragging{opacity:0.5;}/* Success indicator */.success-indicator{color:green;font-weight:bold;display:none;/* Hidden initially */}#target-area.success .success-indicator{display:block;}</style></head><body><h1>Block Drag & Drop Test</h1><divid="source-area"class="area"><h3>Source Area</h3><divid="draggable-block"class="draggable-block"draggable="true"><spanclass="block-content">Drag Me!</span></div></div><divid="target-area"class="area"><h3>Target Area</h3><pclass="success-indicator">Block dropped successfully!</p></div><script>constdraggableBlock=document.getElementById('draggable-block');constsourceArea=document.getElementById('source-area');consttargetArea=document.getElementById('target-area');draggableBlock.addEventListener('dragstart',function(event){event.dataTransfer.setData("text/plain","block-id");// Optional: Set data// Add a class for visual feedbackthis.classList.add('dragging');});draggableBlock.addEventListener('dragend',function(event){// Remove visual feedbackthis.classList.remove('dragging');});targetArea.addEventListener('dragover',function(event){event.preventDefault();// Crucial: Allows dropping});targetArea.addEventListener('drop',function(event){event.preventDefault();// Crucial: Allows dropping// Move the block from source to target// We know the block is the only draggable element in sourcesourceArea.removeChild(draggableBlock);targetArea.appendChild(draggableBlock);// Optional: Add success class to target areatargetArea.classList.add('success');});// Allow dropping back into source area too (for demo purposes)sourceArea.addEventListener('dragover',function(event){event.preventDefault();});sourceArea.addEventListener('drop',function(event){event.preventDefault();// Move the block from target back to sourcetargetArea.removeChild(draggableBlock);sourceArea.appendChild(draggableBlock);// Remove success class from target areatargetArea.classList.remove('success');});</script></body></html>

说明:

  • draggable="true": 必须在可拖拽的元素上设置此属性。
  • CSS: 设置了position: absolute以便在容器内精确定位区块。
  • JavaScript:
    • dragstart: 设置拖拽数据(可选),添加视觉反馈类。
    • dragend: 移除视觉反馈类。
    • dragover:必须调用event.preventDefault(),否则drop事件不会触发。
    • drop:必须调用event.preventDefault()。然后执行元素的移动逻辑(removeChild+appendChild)。
    • 为了演示双向拖拽,source-area也监听了dragoverdrop

2. Pytest + Playwright 测试代码 (test_block_drag_drop.py)

首先,确保安装了必要的库:

pipinstallpytest playwright playwrightinstall

然后,将以下 Python 代码保存为test_block_drag_drop.py

# test_block_drag_drop.pyimportpytestfromplaywright.sync_apiimportPage,expect# Pytest fixture to provide a fresh browser page for each test@pytest.fixture(scope="function")defpage(context):"""Creates a new page for each test function."""page=context.new_page()yieldpage page.close()deftest_drag_block_from_source_to_target(page:Page):""" Tests dragging a block from the source area to the target area. """# 1. Navigate to the HTML file# Update the path to point to where you saved the HTML filepage.goto("file:///absolute/path/to/your/drag_drop_block.html")# 2. Define selectors for the draggable block and the target areasource_area_selector="#source-area"target_area_selector="#target-area"draggable_block_selector="#draggable-block"# 3. Verify initial state: block is in source areaexpect(page.locator(source_area_selector+" "+draggable_block_selector)).to_be_attached()expect(page.locator(target_area_selector+" "+draggable_block_selector)).not_to_be_attached()expect(page.locator(f"{target_area_selector}.success-indicator")).not_to_be_visible()# 4. Perform the drag and drop operationpage.drag_and_drop(draggable_block_selector,target_area_selector)# 5. Verify final state: block is in target areaexpect(page.locator(target_area_selector+" "+draggable_block_selector)).to_be_attached(message="Block should be in target area after drop.")expect(page.locator(source_area_selector+" "+draggable_block_selector)).not_to_be_attached(message="Block should not be in source area after drop.")expect(page.locator(f"{target_area_selector}.success-indicator")).to_be_visible(message="Success indicator should be visible in target area.")deftest_drag_block_back_to_source(page:Page):""" Tests dragging the block back from the target area to the source area. """# 1. Navigate to the HTML filepage.goto("file:///absolute/path/to/your/drag_drop_block.html")# 2. Define selectorssource_area_selector="#source-area"target_area_selector="#target-area"draggable_block_selector="#draggable-block"# 3. First, move the block to the target area (using the previous test's logic or just do it here)# Initial state checkexpect(page.locator(source_area_selector+" "+draggable_block_selector)).to_be_attached()expect(page.locator(target_area_selector+" "+draggable_block_selector)).not_to_be_attached()# Drag to target firstpage.drag_and_drop(draggable_block_selector,target_area_selector)# Confirm it's in targetexpect(page.locator(target_area_selector+" "+draggable_block_selector)).to_be_attached()expect(page.locator(source_area_selector+" "+draggable_block_selector)).not_to_be_attached()expect(page.locator(f"{target_area_selector}.success-indicator")).to_be_visible()# 4. Now, drag the block back from target to sourcepage.drag_and_drop(draggable_block_selector,source_area_selector)# 5. Verify final state: block is back in source areaexpect(page.locator(source_area_selector+" "+draggable_block_selector)).to_be_attached(message="Block should be back in source area after second drop.")expect(page.locator(target_area_selector+" "+draggable_block_selector)).not_to_be_attached(message="Block should not be in target area after second drop.")expect(page.locator(f"{target_area_selector}.success-indicator")).not_to_be_visible(message="Success indicator should be hidden after moving block back to source.")

说明:

  • Fixturepage: 为每个测试函数提供一个新的浏览器页面实例,并在测试结束后自动关闭,确保测试隔离。
  • page.goto(): 导航到你的本地 HTML 文件。务必更新file:///...后面的路径为你实际存放drag_drop_block.html的绝对路径。
  • page.drag_and_drop(source, target): Playwright 提供的核心方法,用于模拟拖放操作。它会处理底层的鼠标事件序列。
  • expect(...): Playwright 的断言库,用于验证 DOM 状态(元素是否存在、是否可见等)。它具有内置的智能等待机制。

3. 运行测试

在终端中,切换到包含test_block_drag_drop.pydrag_drop_block.html的目录,然后运行:

pytest test_block_drag_drop.py -v
  • -v选项提供更详细的输出。

如果配置正确,你应该会看到类似以下的输出,并且浏览器窗口会短暂出现以执行测试:

============================= test session starts ============================== platform linux -- Python 3.x.y, pytest-x.x.x, pluggy-x.x.x rootdir: /path/to/your/test/directory collected 2 items test_block_drag_drop.py::test_drag_block_from_source_to_target PASSED [ 50%] test_block_drag_drop.py::test_drag_block_back_to_source PASSED [100%] ============================== 2 passed in 3.12s ===============================

这表明两个测试(从 source 到 target,以及从 target 回到 source)都成功通过了。

关联文档

【Python知识】使用 Playwright for Python 从零开始搭建自动化测试方案

【自动化测试】Playwright for Python 与 Allure 集成完整指南

【自动化测试】pytest 语法与核心概念

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 12:58:07

开发者首选:IQuest-Coder-V1-Loop免配置镜像快速上手机会

开发者首选&#xff1a;IQuest-Coder-V1-Loop免配置镜像快速上手机会 你是不是也经历过这样的时刻&#xff1a;想试一个新代码模型&#xff0c;结果卡在环境配置上两小时——CUDA版本不匹配、依赖包冲突、模型权重下载失败、显存不够还得手动切分……最后干脆关掉终端&#xf…

作者头像 李华
网站建设 2026/4/16 6:23:33

YOLO26前端展示:HTML+JS实现检测结果可视化

YOLO26前端展示&#xff1a;HTMLJS实现检测结果可视化 最新 YOLO26 官方版训练与推理镜像 本镜像基于 YOLO26 官方代码库 构建&#xff0c;预装了完整的深度学习开发环境&#xff0c;集成了训练、推理及评估所需的所有依赖&#xff0c;开箱即用。 在完成模型推理后&#xff0…

作者头像 李华
网站建设 2026/4/14 6:59:40

Profinet 转 SAE J1939 网关 实现重型车智能控制 西门子 PLC 渣土自卸车改造案例

一、项目背景 某重型商用车制造商针对智能渣土自卸车进行升级改造&#xff0c;需解决车辆底盘动力系统、上装举升系统、电控系统之间的实时协同控制难题。传统车型采用离散式控制架构&#xff0c;发动机、变速箱、举升伺服系统数据互不互通&#xff0c;存在举升动力分配不精准…

作者头像 李华
网站建设 2026/4/16 12:58:15

Tomcat+cpolar 让 Java Web 应用随时随地可访问

Tomcat 作为轻量级 Java 应用服务器&#xff0c;核心功能是稳定托管 Java Servlet 和 JSP 类型的 Web 应用&#xff0c;适配各类中小型 Java 项目的运行需求&#xff0c;适用人群涵盖 Java 开发人员、中小企业运维人员以及编程学习者。它的优点十分突出&#xff0c;部署流程简单…

作者头像 李华
网站建设 2026/4/15 23:24:09

MinerU 2.5-1.2B入门必看:输出路径设置与结果查看教程

MinerU 2.5-1.2B入门必看&#xff1a;输出路径设置与结果查看教程 1. 理解你的任务&#xff1a;为什么需要关注输出路径&#xff1f; 你拿到的这个镜像&#xff0c;不是普通的工具包&#xff0c;而是一套完整的视觉多模态推理系统。它内置了 MinerU 2.5-2509-1.2B 模型和 GLM…

作者头像 李华
网站建设 2026/4/16 12:34:46

5分钟上手Open-AutoGLM:小白也能玩转AI手机助理

5分钟上手Open-AutoGLM&#xff1a;小白也能玩转AI手机助理 1. 什么是Open-AutoGLM&#xff1f; 1.1 让你的手机拥有“超级大脑” 你有没有想过&#xff0c;有一天只要说一句话&#xff0c;手机就能自动帮你完成所有操作&#xff1f;比如&#xff1a;“打开小红书搜美食”、…

作者头像 李华