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/15 14:54:06

Sambert与RVC结合:歌声合成新玩法实战演示

Sambert与RVC结合&#xff1a;歌声合成新玩法实战演示 1. 开箱即用的多情感中文语音合成体验 你有没有试过&#xff0c;输入一段歌词&#xff0c;几秒钟后就听到专业级的中文歌声&#xff1f;不是机械朗读&#xff0c;而是带着喜怒哀乐、呼吸停顿、语气起伏的真实人声——甚至…

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

超指数|试填法

lclc3020也可以开平方写&#xff0c;但是效率不如乘法(统计数组元素频次&#xff0c;先处理数字1得到最长奇数长度&#xff0c;再对其余数不断取平方并统计可连续平方的次数计算最长奇数长度的平方链&#xff0c;最终返回最大长度int ans cnt[1] - 1 | 1; // 奇数将数字1的频次…

作者头像 李华
网站建设 2026/4/12 19:23:05

cv_resnet18图片处理慢?推理速度优化实战解决方案

cv_resnet18图片处理慢&#xff1f;推理速度优化实战解决方案 1. 问题定位&#xff1a;为什么cv_resnet18_ocr-detection跑得慢&#xff1f; 你是不是也遇到过这样的情况&#xff1a;上传一张普通尺寸的截图&#xff0c;WebUI界面卡在“检测中…”长达3秒以上&#xff1b;批量…

作者头像 李华
网站建设 2026/4/13 20:25:19

Emotion2Vec+ Large如何重启服务?run.sh脚本执行命令详解

Emotion2Vec Large如何重启服务&#xff1f;run.sh脚本执行命令详解 1. 系统重启前的必要认知 1.1 为什么需要重启服务 Emotion2Vec Large语音情感识别系统在长时间运行后&#xff0c;可能会遇到几种典型情况&#xff1a;模型推理缓存堆积导致响应变慢、WebUI界面卡顿无法刷…

作者头像 李华
网站建设 2026/4/14 12:10:19

Qwen情感分类不精准?System Prompt调优教程

Qwen情感分类不精准&#xff1f;System Prompt调优教程 1. 问题背景&#xff1a;为什么情感分析会“翻车”&#xff1f; 你有没有遇到过这种情况&#xff1a;输入一句明显开心的话&#xff0c;比如“终于搞定项目了&#xff0c;爽&#xff01;”&#xff0c;结果AI却冷冷地告…

作者头像 李华
网站建设 2026/4/15 21:44:33

Z-Image-Turbo插件机制设想:支持第三方扩展的功能架构设计

Z-Image-Turbo插件机制设想&#xff1a;支持第三方扩展的功能架构设计 1. Z-Image-Turbo_UI界面概览 Z-Image-Turbo不是一款“开箱即用”就完事的图像生成工具&#xff0c;而是一个具备清晰扩展路径的技术平台。它的UI界面是整个能力体系的交互入口&#xff0c;也是插件机制落…

作者头像 李华