全网最细,web自动化测试实战场景(滚动元素的滚动操作)直接上干g货......
前言
使用 selenium 进行 web 自动化测试对我们来说是个常规操作。用了很多次后,我们经常会抱怨 selenium 封装的操作实在是太少了。
比如说 selenium 没有对页面的滚动提供丰富 API , 有的只有一个孤零零的 location_once_scrolled_into_view 方法,把一个元素滚动到可视范围之内。 这远远不能满足日常的需求啊!要知道,现在大多数的网页都需要不停的滚动鼠标加载新内容。
如果是单个窗口的滚动还好,但是遇到一些变态的 ERP 系统就为难了。 每一个页面都像是战国时代的诸侯国,被割裂成一块块相互独立的模块,每个模块都需要滚动操作, 全局的窗口滚动根本就不好使。
我们来看一个例子。
打开禅道的演示页面, 除了窗口本身需要滚动以获取底部的更多内容以外, “最新动态” 和 “我的待办” 都有自己独立的滚动条。

这样的模块实现的技术有几种。有的会把一个区域的内容放在一个 iframe 当中,有的是包裹在一个 div 标签当中。不管是哪一种方式,实际上,我们都可以把他们当成是单个元素进行处理,如何来操作这些可以被滚动的元素呢?
上面说过,官方的 Selenium API当中只有一个 el.location_once_scrolled_into_view 方法把某个元素滚动到可视范围内。这个方法并不够灵活,如果想要更加灵活的操作,比如滑动到底部、滑动一半等,就需要借助 JavaScript 。 基本上,如果 selenium 没有实现的操作,都可以借助 JS 操作。
对于一个网页的 DOM 对象来说呢,有全局的 window.scrollTo 方法,可以对整个窗口实现滚动操作。如果想把网页滚动到最底部,可以在任意网页按 F12 进入开发者工具,选择 console 输入 JS 代码:
window.scrollTo(0, document.body.scrollHeight);

同样的, 在 DOM 对象当中,也实现了对单个元素的滚动操作。 直接设置元素的 scrollTop 属性,表示讲可滚动元素的高度设置到多高。以禅道为例,如果要把 “最新动态” 这个元素向下滚动 800px,可以编写对应的 JS 代码:
// 定位元素
el = document.querySelector("div[data-name=最新动态]>div.panel-body");// 向下滚动 800 像素
el.scrollTop = 800;
如果想滚动到一半,也可以通过元素的 scrollHeight 属性控制:
el.scrollTop = el.scrollHeight * 0.5;
如果元素可以左右滚动,则可以设置元素的 scrollLeft 属性:
el.scrollLeft = el.scrollWidth * 0.5;
通过设置 scrollTop 和 scrollLeft 属性有时候比较麻烦,可以适用 scrollTo 方法简化操作, 表示滚动到一半的宽度,一半的高度;
el.scrollTo(el.scrollWidth * 0.5, el.scrollHeight * 0.5);
也可以适用 scrollBy 表示从现在的位置往右边和下边滑动多少像素点:
el.scrollBy(el.scrollWidth * 0.1, el.scrollHeight * 0.1);

如果希望通过 Selenium 实现滚动操作,可以调用 selenium 当中的 execute_script 方法去执行对应的js语句。要实现上面的效果,可以访问页面之后,执行 JS 语句:
from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://demo.zentao.net/my/")
js_code = """
el = document.querySelector("div[data-name=最新动态]>div.panel-body");
el.scrollTo(0, el.scrollHeight);
"""
driver.execute_script(js_code);
对 selenium 比较熟悉的同学可以封装一个上层 API, 当需要执行滚动操作时,直接调用方法就可以了:
class SeleniumUpAPI:"""Selenium的上层封装"""def __init__(self, driver:Remote):self.driver = driverdef element_scroll_to(self, el:WebElement, x_percent=0, y_percent=0):"""滚动元素到百分比位置.x: 宽度的比率,0.5y: 高度的比率,0.5"""jscode = """arguments[0].scrollTo(arguments[1] * arguments[0].scrollWidth,arguments[2] * arguments[0].scrollHeight);"""self.driver.execute_script(jscode, el, x_percent, y_percent)
最后完整的代码:
import time
from selenium.webdriver import Remote, Chrome
from selenium.webdriver.remote.webelement import WebElementclass SeleniumUpAPI:"""Selenium的上层封装"""def __init__(self, driver:Remote):self.driver = driverdef element_scroll_to(self, el:WebElement, x_percent=0, y_percent=0):"""滚动元素到百分比位置.x: 宽度的比率,0.5y: 高度的比率,0.5"""jscode = """arguments[0].scrollTo(arguments[1] * arguments[0].scrollWidth,arguments[2] * arguments[0].scrollHeight);"""self.driver.execute_script(jscode, el, x_percent, y_percent)def element_scroll_by(self, el:WebElement, x_percent=0, y_percent=0):"""每次滚动多少个像素点,以元素百分比操作x: 宽度的比率,0.1y: 高度的比率,0.1"""jscode = """arguments[0].scrollBy(arguments[1] * arguments[0].scrollWidth,arguments[2] * arguments[0].scrollHeight);"""self.driver.execute_script(jscode, el, x_percent, y_percent)class Element:def scroll(self, x_percent=0, y_percent=0):"""滚动.x: 宽度的比率,0.5y: 高度的比率,0.5"""jscode = """arguments[0].scroll({top:arguments[1] * arguments[0].scrollHeight,left:arguments[1] * arguments[0].scrollWidth});"""self.driver.execute_script(self, el, y_percent, x_percent)if __name__ == "__main__":driver = Chrome()driver.get("https://example.cypress.io/commands/actions")d = SeleniumUpAPI(driver)el = d.driver.find_element("id", "scroll-vertical")el.location_once_scrolled_into_viewtime.sleep(2)d.scroll_element(el, 0.5, 0.5)
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

相关文章:
全网最细,web自动化测试实战场景(滚动元素的滚动操作)直接上干g货......
前言 使用 selenium 进行 web 自动化测试对我们来说是个常规操作。用了很多次后,我们经常会抱怨 selenium 封装的操作实在是太少了。 比如说 selenium 没有对页面的滚动提供丰富 API , 有的只有一个孤零零的 location_once_scrolled_into_view 方法,把…...
Java特性之设计模式【过滤器模式】
一、过滤器模式 概述 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的…...
Linux设备模型(十) - bus/device/device_driver/class
四,驱动的注册 1,struct device_driver结构体 /** * struct device_driver - The basic device driver structure * name: Name of the device driver. * bus: The bus which the device of this driver belongs to. * owner: The module own…...
性能问题分析排查思路之机器(3)
本文是性能问题分析排查思路的展开内容之一,第2篇,主要分为日志1期,机器4期、环境2期共7篇系列文章,本期是第三篇,讲机器(硬件)的网络方面的排查方法和最佳实践。 主要内容如图所示:…...
PostgreSQL安装教程
系统环境 下载压缩包 下载压缩包 解压压缩包 查看解压文件 编译安装 编译 安装 用户权限和环境变量设置 创建用户 创建数据目录和日志目录 设置权限 设置环境变量 初始化数据库 数据库访问控制配置文件 postgresql.conf pg_hba.conf PostgreSQL启动与关闭 手…...
SLAM基础知识:前端和后端
在SLAM中前端和后端是被经常提到的一个概念。但是对于前端和后端的理解有着不同的看法,我的理解是: 前端:前端负责处理传感器数据,特征提取,进行状态估计和地图构建的初步步骤。 后端:后端接受不同时刻的里…...
一文彻底搞懂从输入URL到显示页面的全过程
简略版: 用户输入URL后,浏览器经过URL解析、DNS解析、建立TCP连接、发起HTTP请求、服务器处理请求、接收响应并渲染页面、关闭TCP连接等步骤,最终将页面显示给用户。 详细版: URL解析:浏览器根据用户输入的URL&#x…...
好书安利:《大模型应用开发极简入门:基于GPT-4和ChatGPT》这本书太好了!150页就能让你上手大模型应用开发
文章目录 前言一、ChatGPT 出现,一切都变得不一样了二、蛇尾书特色三、蛇尾书思维导图四、作译者简介五、业内专家书评总结 前言 如果问个问题:有哪些产品曾经创造了伟大的奇迹?ChatGPT 应该会当之无愧入选。仅仅发布 5 天,Chat…...
力扣题库第4题:移动零
题目内容: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 : 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 答案&…...
Java解决IP地址无效化
Java解决IP地址无效化 01 题目 给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本。 所谓无效化 IP 地址,其实就是用 "[.]" 代替了每个 "."。 示例 1: 输入:address "1.1.1.1" 输出…...
[数据结构初阶]队列
鼠鼠我呀,今天写一个基于C语言关于队列的博客,如果有兴趣的读者老爷可以抽空看看,很希望的到各位老爷观点和点评捏! 在此今日,也祝各位小姐姐女生节快乐啊,愿笑容依旧灿烂如初阳,勇气与童真永不…...
MySQL学习Day27——MySQL事务日志
事务的隔离性由锁机制实现,而事务的原子性、一致性和持久性由事务的redo日志和undo日志来保证。其中REDO LOG称为重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性,redo log是存储引擎层生成的日志,记录的是物理级别上的页修改操作,主要为了保证…...
ETAS工具链ISOLAR-AB重要概念,RTE配置,ECU抽取
RTE配置界面,包含ECU抽取关联 首次配置RTE,出现需要勾选的抽取EXTRACT 创建System System制作SWC到ECU的Mapping System制作System Data 的Mapping...
蓝桥杯倒计时 43天 - 前缀和
思路:如果用n^2复杂度暴力会超时。nlogn 可以,利用前缀和化简,提前存储某个位置前的每个石头搬运到该位置和每个石头后搬运到该位置的前缀和On最后直接输出 On。排序花 nlogn #include<bits/stdc.h> using namespace std; typedef pai…...
【Web - 框架 - Vue】随笔 - Vue的简单使用(01) - 快速上手
【Web - 框架 - Vue】随笔 - Vue的简单使用(01) - 快速上手 Vue模板代码 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>模板</title> </head> <body> <div></di…...
【简说八股】Redisson的守护线程是怎么实现的
Redisson Redisson 是一个 Java 语言实现的 Redis SDK 客户端,在使用分布式锁时,它就采用了「自动续期」的方案来避免锁过期,这个守护线程我们一般也把它叫做「看门狗」线程。 Redission是一个在Java环境中使用的开源的分布式缓存和分布式锁实…...
WPS/Office 好用的Word插件-查找替换
例如:一片文档:…………泰山…………泰(少打了山字)………… 要是把“泰”查找替换为“泰山”,就会把前面的“泰山”变成“泰山山”,这种问题除了再把“泰山山”查找替换为“泰山”,有没有更简单…...
Go 简单设计和实现可扩展、高性能的泛型本地缓存
相信大家对于缓存这个词都不陌生,但凡追求高性能的业务场景,一般都会使用缓存,它可以提高数据的检索速度,减少数据库的压力。缓存大体分为两类:本地缓存和分布式缓存(如 Redis)。本地缓存适用于…...
Vue.js 深度解析:模板编译原理与过程
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
Java多线程——如何保证原子性
目录 引出原子性保障原子性CAS 创建线程有几种方式?方式1:继承Thread创建线程方式2:通过Runnable方式3:通过Callable创建线程方式4:通过线程池概述ThreadPoolExecutor API代码实现源码分析工作原理:线程池的…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

