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 主要分为:

  1. 显式等待(Explicit Waits)
  2. 隐式等待(Implicit Waits)
  3. 自定义等待(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,不过我们可以使用findElements
   doSometing();
}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异常的,默认不做处理往外抛)
  • 定制超时后的异常消息文本
    @Test
    public 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种等待机制(包括默认的),有了这些等待,可以大大的提高我们测试的准确性和稳定性。这几种机制没有哪个最好,我们需要根据实际的情况选择最合适的等待。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626751.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【保姆级介绍自动化的讲解】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

mysql根据字段值关联查不同表

mysql根据字段值关联查不同表&#xff1a; 实现&#xff1a; 使用left join 结合case when 判断直接取值&#xff1a; select mp.member_id ,mp.store_id, case mp.store_type when 1 then bs.store_namewhen 2 then sc.store_namewhen 3 then be.store_name end as store_na…

Windows / Linux 查看计算机支持的最大内存

该操作一般用不到&#xff0c;主要用于给计算机扩展内存用。 一、Windows 系统 以管理员身份运行 cmd 1、查看主板最大支持内存容量 wmic memphysical get maxcapacity /format:value将返回值值是以KB为单位的&#xff0c;除以 1024&#xff0c;再除以 1024&#xff0c;即…

银行核心背后的落地工程体系丨混沌测试的场景设计与实战演练

本文作者&#xff1a; 张显华、窦智浩、卢进文 与集中式架构相比&#xff0c;分布式架构的系统复杂性呈指数级增长&#xff0c;混沌工程在信创转型、分布式架构转型、小机下移等过程中有效保障了生产的稳定性。本文分享了 TiDB 分布式数据库在银行核心业务系统落地中进行混沌测…

【AI学习】对指令微调(instruction tuning)的理解

前面对微调&#xff08;Fine-tuning&#xff09;的学习中&#xff0c;提到指令微调。当时&#xff0c;不清楚何为指令微调&#xff0c;也一直没来得及仔细学习。 什么是指令微调&#xff1f;LLM经过预训练后&#xff0c;通过指令微调提升模型的指令遵循能力。所谓指令&#xf…

【微记录】dmidecode是干什么的?常用来做什么?如何查看系统支持的PCIe版本号(本质:标准,Desktop Management Interface)

是什么 dmidecode 是一个在 Linux 系统提取硬件信息的命令行工具。DMI 代表桌面管理接口&#xff08;Desktop Management Interface&#xff09;&#xff0c;是一种标准&#xff0c;收集桌面计算机的硬件信息&#xff0c;包括系统制造商、序列号、BIOS 信息、系统资产标签等。…

AI图像生成-基本步骤

模型板块 1、新建采样器&#xff1a;新建节点-》采样器-》K采样器 2、拖动模型节点后放开&#xff0c;选择checkpoint加载器&#xff08;简易&#xff09;&#xff0c;模型新建成功 提示词板块 1、拖动正面条件节点后放开&#xff0c;选择CLIP文本编码器&#xff0c;模型新建…

UV胶的应用场景有哪些?

UV胶是一种特殊的胶水&#xff0c;其固化过程需要紫外光照射。它具有快速固化、高强度、无溶剂挥发等优点&#xff0c;因此在许多应用场景中被广泛使用。UV胶的应用场景非常广泛&#xff0c;包括但不限于以下几个方面&#xff1a; 1.电子产品组装: UV胶在电子产品的组装中扮演…

SHELL-双重循环习题练习

1.99乘法表 #!/bin/bash #99乘法表for ((second1; second<9; second)) dofor ((first1; first<second; first))do echo -n -e "${first}*${second}$[first*second]\t" done echo done ######### 首先定义了一个外循环变量second&#xff0c;初始值为1&am…

【JavaEE】Spring Web MVC入门:掌握Spring的MVC框架基础

目录 Spring Web MVC什么是Spring Web MVCMVC 定义什么是Spring MVC 学习Spring MVC1. 项目准备2. 建立连接 Spring Web MVC 什么是Spring Web MVC 官⽅对于 Spring MVC 的描述是这样的&#xff1a; Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀…

【go项目01_学习记录12】

代码组织 1 代码结构2 重构与测试2.1 安装测试功能2.2 testify 的常用断言函数 3 表组测试 1 代码结构 所有的代码写在一个main.go文件里面&#xff0c;GO编译器也是可以正常执行的。但是当代码量很庞大时&#xff0c;很难进行维护。 Go Web 程序的代码组织 单文件——反模式…

C51 单片机编程模板及编码规范

文章目录 一、C51 单片机模板创建1. 新建工程及选型2. 创建主程序文件3. 创建主程序的头文件4. 编译配置5. 其他 二、C51 的编码规范 在查阅了很多关于 C51 单片机的程序后&#xff0c;个人感觉目前网上有关 C51 单片机程序的质量参差不齐&#xff0c;很多程序的代码风格及其糟…

Kubernetes——CNI网络组件

目录 一、Kubernetes三种接口 二、Kubernetes三种网络 三、VLAN与VXLAN 1.VLAN 2.VXLAN 3.区别 3.1作用不同 3.2vxlan支持更多的二层网络 3.3已有的网络路径利用效率更高 3.4防止物理交换机Mac表耗尽 3.5相对VLAN技术&#xff0c;VXLAN技术具有以下优势 四、CNI网…

设计模式-动态代理

目录 定义 代理模式的优缺点 优点 缺点 应用场景 静态代理 动态代理 相关资料 定义 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它的概念很简单&#xff0c;它通过创建一个代理对象来控制对原始对象的访问。代理模式主要涉及两个…

分布式搜索-elaticsearch基础 概念

什么是elaticsearch: 倒排索引&#xff1a;就是将要查询的内容分成一个个词条&#xff0c;在将词条文档id存入&#xff0c;词条是唯一的。 文档词条总结: mysql和Elasticsearch概念对比: 架构: 基本概念总结:

uniapp 实现下拉刷新 下滑更新

效果图 在app或者小程序中向下滑动 会出现刷新数据 ,而上拉到底 需要更新数据 功能实现 主要俩种方式 依赖生命周期 在page.json中开启 page.json "style" : {"navigationBarTitleText" : "小小练习","backgroundTextStyle": &qu…

Transformer模型详解05-Decoder 结构

文章目录 简介结构原理第一个 Multi-Head Attention第二个 Multi-Head AttentionSoftmax 预测输出单词 简介 Transformer 模型由编码器&#xff08;Encoder&#xff09;和解码器&#xff08;Decoder&#xff09;两部分组成。这里我会着重描述解码器的结构以及在预训练、输入输…

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读 Abstract1 Introduction2 Related Work3 Proposed Approach4 Experiments5 Conclusion 文章信息&#xff1a; 原文链接&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/4…

期权(1):基本概念,权利金,定金,买方,卖方,零和游戏,对赌协议

期权是合约&#xff0c;权利金就是定金&#xff01; 合约到期时 买方可以选择行权&#xff0c;也可以选择不行权。代价就是定金损失。因此亏损封顶&#xff0c;但盈利无限。卖方赚的就是买方的定金&#xff0c;盈利封顶&#xff0c;但亏损无限。 从这里&#xff0c;我们看出…

短视频拍摄+直播间搭建视觉艺术实战课:手把手场景演绎 从0-1短视频-8节课

抖音短视频和直播间你是否遇到这些问题? 短视频是用手机拍还是相机拍?画面怎么拍都没有质感 短视频产量低&#xff0c;拍的素材可用率低 看到别人用手机就能把短视频拍好自己却无从下手 明明已经打了好几盏灯了,但是画面还是比较暗 直播软件参数不会设置&#xff0c;电脑…