news 2026/6/15 21:07:08

【自动化测试】 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/6/15 19:24:27

Llama3-8B语音助手后端:ASR+NLP联合部署实战

Llama3-8B语音助手后端&#xff1a;ASRNLP联合部署实战 1. 为什么选Llama3-8B做语音助手的“大脑” 你有没有试过对着手机说“帮我写一封辞职信”&#xff0c;结果AI生成的内容要么太生硬&#xff0c;要么跑题千里&#xff1f;问题往往不在语音识别不准&#xff0c;而在于听懂…

作者头像 李华
网站建设 2026/6/15 13:36:24

Llama3-8B推理延迟高?vLLM批处理优化实战案例

Llama3-8B推理延迟高&#xff1f;vLLM批处理优化实战案例 1. 问题背景&#xff1a;Llama3-8B的性能瓶颈在哪里&#xff1f; Meta-Llama-3-8B-Instruct 是 Meta 在 2024 年 4 月推出的中等规模大模型&#xff0c;凭借其 80 亿参数、单卡可部署、支持 8k 上下文和 Apache 2.0 类…

作者头像 李华
网站建设 2026/6/15 13:40:29

javascript之do-while循环

javascript的do-while循环的区别是do-while是先执行一次&#xff0c;然后接着循环while是不符合循环条件就结束循环&#xff0c;循环的次数可能为0do-while的语法do{循环体}while(表达式&#xff09;最简单案例&#xff0c;循环十次输出“好好学习&#xff0c;天天向上”let i1…

作者头像 李华
网站建设 2026/6/15 19:35:05

sql语言之order by语句

order by是进行排序&#xff0c;asc是升序排序&#xff0c;也就是从小到大排列&#xff0c;desc是降序排列&#xff0c;从大到小排列语法格式select 字段名 from 表名 order by 排序的字段名 asc(或者desc)数据表如下图现在要根据id进行降序排序select "id","co…

作者头像 李华
网站建设 2026/6/15 17:16:52

YOLO26安全合规考虑:数据隐私与模型可解释性

YOLO26安全合规考虑&#xff1a;数据隐私与模型可解释性 随着AI技术在工业、安防、医疗等领域的广泛应用&#xff0c;目标检测模型如YOLO系列已不再只是追求精度和速度的工具&#xff0c;其背后的安全性、合规性问题也日益受到关注。尤其是在处理敏感场景&#xff08;如公共场…

作者头像 李华