Selenium 自动化 —— 四种等待(wait)机制
更多关于Selenium的知识请访问CSND论坛“兰亭序咖啡”的专栏:
专栏《Selenium 从入门到精通》
目录
目录
需要等待的场景
自己实现等待逻辑
Selenium 提供的三种等待机制
隐式等待(Implicit Waits)
隐式等待的优点
隐式等待的缺点
显式等待(Explicit Waits)
显式等待的优点
显式等待的缺点
自定义等待(Custom Waits)
自定义等待的优点
自定义等待的缺点
总结
需要等待的场景
在 UI 自动化时,我们通常需要等待,比如以下场景:
- 登录后,页面会跳转,我们需要等待页面完全加载(否则,没ready访问元素会找不到)
- 点击搜索按钮后,页面异步刷新,我们需要等待加载框消失(否则,结果还没有update,拿到错误的数据)
- 页面满足部分条件后,预定按钮才会可以点击,我们需要等待它变成激活状态(否则,按钮还是disabled的状态,出现点击报错)
- ……
总之,这些等待,对于我们测试的稳定性和正确性非常重要。
自己实现等待逻辑
最简单的方法是,我们自己写一个While循环不断地检查条件是否满足。
while(true){if(checkCondition()){doSomeThing();}else{Thread.sleep(n秒);}
}
不过这么做不但麻烦,自己实现也容易出错。值得庆幸的是,Selenium 就提供了内置的机制,帮助我们实现等待的功能。
学习中可以造轮子,帮助我们理解原理,但是生产项目中尽量用成熟的轮子。
Selenium 提供的三种等待机制
Selenium 查找元素默认是没有等待的,也就是说找到了就返回WebElement,否则就抛出异常。
我们测试一下,没有配置任何等待:
@Test
public void testDefault(){WebDriver driver = null;long begin = 0;try{driver = new ChromeDriver();driver.get("https://mail.163.com");begin = System.currentTimeMillis();WebElement element = driver.findElement(By.id("inexistence"));}finally {long end = System.currentTimeMillis();log.info("花费时间:{}毫秒", end-begin);driver.close();}
}
日志打印:-- 花费时间:100毫秒(这个很短的时间是findElement本身执行遍历dom需要的一些时间)
抛出异常:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#inexistence"}
Selenium 提供了等待机制,我们可以通过配置或者调用,很方便的实现我们等待的需求。
Selenium 主要分为:
- 显式等待(Explicit Waits)
- 隐式等待(Implicit Waits)
- 自定义等待(Custom Waits)
下面我们分别介绍它们。
隐式等待(Implicit Waits)
隐式等待是全局设置,设置一次后,对整个WebDriver实例生命周期内的所有查找元素操作生效。
它会让Webdriver在寻找元素时,如果元素没有立即找到,就等待一段时间再查找,直到超过设定的最大时间或者找到元素为止。
下面是我们显式等待的测试代码:
@Test
public void testImplicit (){WebDriver driver = null;long begin = 0;try{driver = new ChromeDriver();// 设置隐式等待时间为10秒driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));driver.get("https://mail.163.com");WebElement element = driver.findElement(By.id("inexistence"));}finally {long end = System.currentTimeMillis();log.info("花费时间:{}毫秒", end-begin);driver.close();}
}
其实相对于默认的机制,我们只是加了一行配置的代码:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
但是效果却非常大:
日志打印:-- 花费时间:10129毫秒(去除方法本身的执行时间,等待时间大于就是10秒)
抛出的异常还是找不到元素:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#inexistence"}
当然不是说一定要等待这么久,如果找到了元素,会立刻返回!
等待时间只是超时时间。
隐式等待的优点
简单,一条配置,全局都有效。
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
隐式等待的缺点
等待的时间是全局的,但是不同元素、不同页面、甚至不同网络的加载情况不一样,不能对每种元素设置不同的等待时间。
使用不当的话,会对整个测试的效率造成非常大的影响。
比如,我们很多地方会用检查一个元素存不存在,来判断不同的情况。
Element ele = findElement(XXX);
if(ele == null){ // 当然默认找不到元素会抛异常而不是为null,不过我们可以使用findElementsdoSometing();
}else{doOtherthing();
}
如果很多地方都这样检查,那么花费的时间会很长很长!
显式等待(Explicit Waits)
上面说过,隐式等待是全局一致的,如果我们想更灵活的等待,对一些元素希望等待时间可以短一些,对另一些希望能够多等一些时间,这时显式等待就派上用场了。
@Test
public void testExplicitWait(){WebDriver driver = null;long begin = 0;try{driver = new ChromeDriver();driver.get("https://mail.163.com");begin = System.currentTimeMillis();// 等待id为"someId"的元素出现WebElement element = new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.presenceOfElementLocated(By.id("someId")));// 等待加载图标(class为"loading-spinner")消失new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-spinner")));}finally {long end = System.currentTimeMillis();log.info("花费时间:{}毫秒", end-begin);driver.close();}
}
可以看到,我们可以对不同的元素设置不同的等待时间
new WebDriverWait(driver, java.time.Duration.ofSeconds(10))
这些wait,其实也是可以复用的,比如10s的等待的Wait,可以被用来检查各种元素。
还能对它们设置不同的条件,比如等待元素的出现、消失
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("someId")));
wait..until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-spinner")));
ExpectedConditions 类内置了常用的各种等待条件,满足我们大部分的场景:
更完整的列表,请查看这个类的方法列表
显式等待的优点
更精细更灵活的控制:
1. 对不同的元素设置不同的等待时间
2. 对不同的元素设置不同的等待条件
显式等待的缺点
更复杂,维护起来也麻烦。
如果不是很熟悉,乱使用,容易适得其反。
自定义等待(Custom Waits)
显式等待看上去很强大了,是不是就很完美了呢?
特殊场景下,如果你又更苛刻的要求,你也可以定制化自己的等待,进一步的更精细的控制等待,比如:
- 自定义重试检查的周期
- 找不到抛异常时,想根据Exception做一些处理(因为隐式、显式等待超时后都是直接抛出Timeout异常的,默认不做处理往外抛)
- 定制超时后的异常消息文本
@Testpublic void test() {WebDriver driver = null;long begin = 0;try {driver = new ChromeDriver();driver.get("https://mail.163.com");begin = System.currentTimeMillis();Wait<WebDriver> wait =new FluentWait<>(driver).withTimeout(Duration.ofSeconds(2)).pollingEvery(Duration.ofMillis(300)).ignoring(ElementNotInteractableException.class);wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("no-no")));} finally {long end = System.currentTimeMillis();log.info("花费时间:{}毫秒", end - begin);driver.close();}}
自定义等待的优点
更灵活、更精细的控制
自定义等待的缺点
太复杂,使用前请认真思考,我们真的需要这么细致的控制吗?
总结
本文介绍了4种等待机制(包括默认的),有了这些等待,可以大大的提高我们测试的准确性和稳定性。这几种机制没有哪个最好,我们需要根据实际的情况选择最合适的等待。
相关文章:

Selenium 自动化 —— 四种等待(wait)机制
更多关于Selenium的知识请访问CSND论坛“兰亭序咖啡”的专栏:专栏《Selenium 从入门到精通》 目录 目录 需要等待的场景 自己实现等待逻辑 Selenium 提供的三种等待机制 隐式等待(Implicit Waits) 隐式等待的优点 隐式等待的缺点 …...

每日两题 / 437. 路径总和 III 105. 从前序与中序遍历序列构造二叉树(LeetCode热题100)
437. 路径总和 III - 力扣(LeetCode) 前序遍历时,维护当前路径(根节点开始)的路径和,同时记录路径上每个节点的路径和 假设当前路径和为cur,那么ans 路径和(cur - target)的出现次数 /*** D…...

matlab使用2-基础绘图
matlab使用2-基础绘图 文章目录 matlab使用2-基础绘图1. 二维平面绘图2. 三维立体绘图3. 图形窗口的分割 1. 二维平面绘图 % 创建一些二维数据 x 0:0.01:10; % x轴的数据点,从0到10,间隔为0.01 y sin(x); % y轴的数据点,是x的正弦…...
嵌入式开发四大平台介绍
MCU(Micro Control Unit)四大平台介绍) 单片机优点:缺点:总结: DSP digital signal processingARM优点:缺点:总结 FPGA什么事FPGA(集成元件库)FPGA开发方法—…...

《Python编程从入门到实践》day28
# 昨日知识点回顾 安装Matplotlib 绘制简单的折线图 # 今日知识点学习 15.2.1 修改标签文字和线条粗细 # module backend_interagg has no attribute FigureCanvas. Did you mean: FigureCanvasAgg? # 解决办法:matplotlib切换图形界面显示终端TkAgg。 #…...

STC8增强型单片机开发【定时器Timer⭐】
目录 一、引言 二、定时器基础知识 三、STC8定时器配置 四、代码示例 五、总结 一、引言 在单片机开发中,定时器(Timer)是一个极其重要的组件,它允许开发者基于时间触发各种事件或任务。STC8增强型单片机作为一款功能丰富的…...

C语言实训项目源码-02餐厅饭卡管理系统-C语言实训C语言大作业小项目
C语言餐厅饭卡管理系统 一、主要功能 主要功能模块 页面名称 实现功能 负责人 进入页面 进入程序 主函数 系统主要功能 修改密码函数 修改密码 充值,显示函数 饭卡充值与信息显示 购买饭菜…...

Linux第四节--常见的指令介绍集合(持续更新中)
点赞关注不迷路!本节涉及初识Linux第四节,主要为常见的几条指令介绍。 如果文章对你有帮助的话 欢迎 评论💬 点赞👍🏻 收藏 ✨ 加关注👀 期待与你共同进步! 1. more指令 语法:more [选项][文件]…...

Apache Sqoop:高效数据传输工具搭建与使用教程
目录 引言一、环境准备二、安装sqoop下载sqoop包解压文件 三、配置Sqoop下载mysql驱动拷贝hive的归档文件配置环境变量修改sqoop-env.sh配置文件替换版本的commons-lang的jar包 验证Sqoop安装查看Sqoop版本测试Sqoop连接MySQL数据库是否成功查看数据库查看数据表去除警告信息 四…...

【C++初阶】第十一站:list的介绍及使用
目录 list的介绍及使用 1.list的含义 2.list的介绍 3.list的使用 1.list的构造 2.list iterator的使用 3.list capacity 4.list element access 5 list modifiers 尾插尾删 和 头插头删 insert 和 erase resize swap clear 6.list sort and reverse 7.list copy vector copy li…...

【devops】Linux 日常磁盘清理 ubuntu 清理大文件 docker 镜像清理
日常磁盘清理 1、查找大文件 find / -type f -size 1G2、清理docker无用镜像(drone产生的残余镜像文件) docker system prune -a一、清理服务器磁盘 1、查找大文件 在Ubuntu系统中,你可以使用find命令来查找大文件。find命令是一个强大的…...
2024年资阳市企业技术中心申报条件、流程要求及支持政策须知
第一章 总则 第一条 为深入贯彻中央、省、市大力实施创新驱动发展战略的部署要求,进一步强化企业技术创新主体地位,引导和支持企业增强技术创新能力,健全技术创新市场导向机制,规范我市企业技术中心(下称“市企业技术…...

社交媒体数据恢复:如流
如流,原名百度Hi,是百度公司开发的一款即时通讯软体。百度Hi具备文字消息、视讯、通话、文件传输等功能。 查找备份:如果您之前有备份如流中的数据,您可以尝试从备份中恢复。如流支持备份至云端,如百度网盘等。 联系客…...

【微信小程序开发(从零到一)【婚礼邀请函】制作】——任务分析和效果实现的前期准备(1)
👨💻个人主页:开发者-曼亿点 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 曼亿点 原创 👨💻 收录于专栏:…...
独孤思维:模仿别人赚钱太难,很痛苦
01 独孤早年混群的时候,想着成为群红,引流。 结果不得其法,别人要什么项目,我就把满是钩子的副业资料发群里。 被群主踢了出去。 我当时还不理解。 后来自己做了社群以后,才明白,这种行为,…...

图片转base64【Vue + 纯Html】
1.template <el-form-item label"图片"><div class"image-upload-container"><input type"file" id"imageUpload" class"image-upload" change"convertToBase64" /><label for"imageU…...

【从零开始学习Redis | 第十一篇】快速介绍Redis持久化策略
前言: Redis 作为一种快速、高效的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景。然而,由于其特性是基于内存的,一旦服务器进程退出,内存中的数据就会丢失。为了解决这一问题,Redis 提供了持久…...
在Ubuntu中如何解压zip压缩包??
2024年5月15日,周三上午 使用 unzip 命令 unzip 文件名.zip这会将压缩包中的内容解压到当前目录。如果想解压到特定目录,可以使用 -d 选项,例如: unzip 文件名.zip -d 目标目录使用 7-zip 还可以安装 7-zip 工具来解压 ZIP 文件。…...

LeetCode 126题:单词接龙 II
❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣! 推荐:数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航: LeetCode解锁100…...
5.14(Vue2)
1.单页应用程序是指所有功能都在一个html页面上 单页面应用程序,之所以开发效率高,性能好,应用体验好,最大的原因就是:页面按需更新。 2.Vue中的路由 路径和组件的映射关系 Vue中的路由插件:VueRouter&…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...