Appium等待机制--强制等待、隐式等待、显式等待

书接上回,Appium高级操作--其他操作-CSDN博客文章浏览阅读182次,点赞6次,收藏7次。书接上回Appium高级操作--从源码角度解析--模拟复杂手势操作-CSDN博客。 https://blog.csdn.net/fantasy_4/article/details/146162851主要讲解了Appium的一些高级操作,比如基于ActionChain类的,操作系统API的方法等,便于解决比较复杂的场景下的手势模拟。不过在自动化的过程中,经常会出现寻找查找元素时间过长,等待时间设置不合理导致脚本执行时间过程,最终的结果就是自动化运行的速度不如'手工'操作。为了解决上述问题,本篇文章主要讲解一下Appium的等待机制

1.影响页面加载时长的因素

做UI自动化的同学可能多数都会遇到这样的问题,执行跳转页面后再去定位,经常会提示找不到元素,造成找不到元素的原因除了有元素定位本身的问题之外,还可能的原因是页面本身的加载时长过长,那影响页面加载时长的因素有哪些呢?

  • 移动端性能

市面上出现生产使用的移动端各不相同,不同的配制,不同的机型,不同的系统,甚至不同的操作系统版本,因此在这些设备上安装同一款软件就会产生不同的加载时长。如果调试脚本时使用的是一款配置较好的手机,而实际运行脚本的是另外的配置较差的手机,就会出现明明调试的时候没问题,正式运行就会出错。

  • 服务端性能

如果执行自动化的服务端还部署着其他服务,比如缺陷管理工具、代码管理工具等,这样服务端存在大量并发用户请求,就会造成自动化执行时会花费更多的时间才能相应。

  • 网络因素

如果被测试APP中的Web页面包含大量图片,或者请求中存在低劣无效的代码就会产生大量的数据请求,这是网络的稳定至关重要。

2.强制等待

所谓强制等待,就是在执行自动化的过程中加上一个强制的等待时间,等待时间结束后期望要跳转的页面能够加载完毕,如果没有那可能还是要调整时间。

通常使用Python time模块的time.sleep(s) 来实现

优点:调试代码时,能够便于我们观察脚本的执行情况

缺点:强制等待会导致执行脚本的时间不一致,设置的等待时间参差不齐,尤其是脚本很多时,就会造成脚本越执行越慢。

那么有没有一种更智能的等待方式呢?能够实现找到元素就立刻进行下一步操作,如果找不到元素就进行等待呢?

3.隐性等待

隐性等待就能够完美解决上面提出的问题。

Appium的隐性等待继承了Selenium的implicitly_wait()方法。

driver.implicitly_wait(5) # 隐性等待5s

优点:可以很智能判断是否需要执行相应等待时长,一旦设置就会实例化整个会话的生命周期

缺点:会减缓测试速度(尤其是在需要查找某个元素不存在时的用例,会平白浪费时间等待查找该元素是不是存在),而且会干扰显性等待,不建议使用隐形等待和显性等待混用

4.显性等待

显性等待能够更精细化的定制一些执行条件,等到条件满足会后在进行下一步操作。

Appium并没有引入Selenium的WebDriverWait类,因此要使用显性等待,只能从Selenium中引入,主要由以下两部分实现显性等待

1)Selenium中的WebDriver类:定义超时时间、轮询频率等

2)Expected_conditions模块:提供一些预期条件作为测试脚本进行后续操作的判断依据

  • 显性等待整体语法结构

WebdriverWait(dirver, 超时时间,轮询频率, 忽略异常).until(可执行方法,超时后返回的信息)

上面代码的含义:每隔一段时间,一定频次,就会调用可执行方法,直到方法返回True,如果超时则返回超时后的信息。

注意until中的可执行方法必须是可以调用的,即这个对象一定有__call__()方法

  • WebDriverWait类源码分析

def __init__(self,driver: D,timeout: float,poll_frequency: float = POLL_FREQUENCY,ignored_exceptions: Optional[WaitExcTypes] = None,
):"""Constructor, takes a WebDriver instance and timeout in seconds.
​Attributes:----------driver- Instance of WebDriver (Ie, Firefox, Chrome or Remote) ora WebElement
​timeout- Number of seconds before timing out
​poll_frequency- Sleep interval between calls- By default, it is 0.5 second.
​ignored_exceptions- Iterable structure of exception classes ignored during calls.- By default, it contains NoSuchElementException only.

WebDriverWait类创建对象可以传入4个参数:

  • driver:WebDriver实例化-必传

  • timeout:超时时间-必传

  • poll_frequency:轮询频率-非必传

  • ignored_exceptions:可忽略异常-非必传

WebDriverWait类提供两个方法until()until_not(),两个方法传参相同

  • method:可以调用方法-必传,

  • str: 异常信息-非必传

两个方法的含义不同:

 untiluntil_not
等待逻辑等待条件变为 True等待条件变为 False
适用场景等待元素出现或满足特定条件。等待元素消失或不满足特定条件。
异常处理如果条件未变为 True,抛出 TimeoutException如果条件未变为 False,抛出 TimeoutException
返回值返回满足条件的对象(如元素)无返回值(仅等待条件变为 False

(使用的Selenium是配套Appium-Python-Client一起下载的,版本是 4.29.0,其中until_not的方法注释(定义部分)有错误)如下图

  • Expected_conditions模块

Expected_conditions模块是selenium提供的各种预期条件,Expected_conditions有多种方法,黑体字相对比较常用

方法描述
title_is(title: str)判断页面的title和预期title是否一致,一直则返回True,否则返回False
title_contains(title: str)判断页面的title是否包含预期title是否一致,大小写敏感一直则返回True,否则返回False
presence_of_element_located(locator: Tuple[str, str])用于检查某个元素是否存在于DOM中,但不一定可见,一旦找到元素则返回WebElement
presence_of_all_elements_located(locator: Tuple[str, str])用于检查所有元素是否存在,如果存在返回所有匹配的元素的列表,否则报错
url_matches(pattern: str)检查当前driver的url是否包含字符串,包含返回True,不包含返回False
url_to_be(url: str)检查当前driver的url与预期值是否完全匹配,匹配返回True,否则返回False
url_changes(url: str)检查当前url和预期值是否一致,不一致返回True,一直返回False
url_contains(url: str)检查当前driver的url是否包含字符串,包含返回True,不包含返回False
visibility_of(element: WebElement)参数是WebElement,判断元素是否在当前页面的DOM中并可见,若是返回True,否则返回False
visibility_of_element_located(locator: Tuple[str, str] )参数是locator,判断元素是否在当前页面的DOM中并可见,若是返回True,否则返回False
visibility_of_any_elements_located(locator: Tuple[str, str])至少能定位到一个可见元素,是返回列表 否则报错
visibility_of_all_elements_located(locator: Tuple[str, str] )找到所有符合条件的可见元素,是返回列表 否则报错
invisibility_of_element_located(locator: Union[WebElement, Tuple[str, str]] )判断不可见元素是否存在
invisibility_of_element(element: Union[WebElement, Tuple[str, str]] )判断元素是都不可见
staleness_of(element: WebElement)判断刷新后,元素是否仍然在DOM中,如果在返回False,否则返回True
frame_to_be_available_and_switch_to_it(locator: Union[Tuple[str, str], str])判断frame_locator是否存在,存在则跳转到对应frame并返回True,否则返回False
text_to_be_present_in_element(locator: Tuple[str, str], text_: str)判断text是否出现在元素中
text_to_be_present_in_element_value(locator: Tuple[str, str], text_: str )判断text是否出现在元素的value属性中
text_to_be_present_in_element_attribute(locator: Tuple[str, str], attribute: str, text: str )判断text是否出现在元素的属性中
element_to_be_clickable(mark: Union[WebElement, Tuple[str, str]] )检查元素是否可见并可以被单击并且单击
element_to_be_selected(element: WebElement)入参为WebElement,被定位的元素是否是被选中的,返回布尔值
element_located_to_be_selected(locator: Tuple[str, str])入参为locator,被定位的元素是否是被选中的,返回布尔值
element_selection_state_to_be(element: WebElement, is_selected: bool)检查给定元素是否是被选中的
element_located_selection_state_to_be(locator: Tuple[str, str], is_selected: bool )查找元素并检查指定的选择状态是否处于该状态的期望,返回布尔值
new_window_is_opened(current_handles: List[str])传入当前窗口的句柄,判断是否有新窗口打开,返回布尔值
number_of_windows_to_be(num_windows: int)判断窗口数量是否符合预期
alert_is_present()判断是否有alert,如果有,切换到alert,否则返回False
  • 代码演示

    from appium import webdriver
    from appium.options.android import UiAutomator2Options
    from appium.webdriver.common.appiumby import AppiumBy
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    ​
    desired_caps = {"platformName": "Android","deviceName": "XXXXXXXXXXXXX","appPackage": "com.sankuai.movie","appActivity": "com.sankuai.movie.MovieMainActivity","automationName": "UiAutomator2"
    }
    ​
    print("Desired Capabilities: ", desired_caps)
    ​
    driver = webdriver.Remote("http://localhost:4723", options=UiAutomator2Options().load_capabilities(desired_caps))
    ​
    ​
    try:agree_id = "com.sankuai.movie:id/cyf"ele1 = WebDriverWait(driver, 10).until(expected_conditions.presence_of_element_located((AppiumBy.ID, agree_id)))ele1.click()my_id = 'com.sankuai.movie:id/b50'ele2 = WebDriverWait(driver, 10).until(expected_conditions.invisibility_of_element_located((AppiumBy.ID, my_id)))# WebDriverWait(driver, 10).until_not()ele2.click()ele4 = WebDriverWait(driver,10).until(expected_conditions.element_to_be_clickable((AppiumBy.ID, 'com.sankuai.movie:id/b50')))ele4.click()
    ​
    except Exception as e:raise e
    ​
    finally:# 关闭 Appium 会话driver.quit()
    ​
  • 自定义等待条件

就是在expected_conditions模块不满足个需求的情况下,可以使用lambda表达式来自定义等待条件。

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
​
ele3 = WebDriverWait(driver, 10).until(lambda driver: driver.find_elements(AppiumBy.ID, 'com.sankuai.movie:id/b50'))
ele3.click()

5.总结三种等待区别

 强制等待隐性等待显性等待
实现方式time.sleep(3)driver.implicitly_wait(5)Webdriver类+expected_conditions模块
灵活程度不管是否找元素,必须等待响应时间找到元素则不等待,否则等待在固定之间
生命周期当前行整个会话每个条件需要单独设置
使用场景脚本调试页面加载时间相对固定的全局等待场景,不建议跟显性等待混用动态页面或需要等待特定条件的复杂场景,建议多使用

下一章介可能会讲解一些关于自动化框架搭建相关内容,可以期待一下哦~

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【架构艺术】Go语言微服务monorepo的代码架构设计

近期因为项目架构升级原因,笔者着手调研一些go项目monorepo的代码架构设计,目标是长期把既有微服务项目重要的部分都转移到monorepo上面,让代码更容易维护,协作开发更加方便。虽然经验不多,但既然有了初步的调研&#…

深入解析 JVM —— 从基础概念到实战调优的全链路学习指南

文章目录 一、为什么要学习 JVM?1. 面试必备与技能提升2. 性能优化与问题诊断3. 编写高质量代码 二、JVM 基础概念与体系结构1. JVM 简介2. JDK、JRE 与 JVM 三、JVM 内存模型1. 线程私有区2. 线程共享区 四、类加载机制与双亲委派1. 类加载过程2. 双亲委派模型3. 动…

前端及后端实现csv文件下载功能

方法一、 前端内容: const url window.URL.createObjectURL(new Blob([res.data])); const link document.createElement(a); link.href url; const fileNameDateTime getFormattedDateTime(); const filename "用户提现列表"fileNameDateTime.csv…

QT中委托QStyledItemDelegate的使用

目录 一、子类化委托 二、委托方法实现 1)createEditor 2)setEditorData 3)setModelData 4)updateEditorGeometry 三、委托使用 四、总结 Qt的数据容器控件采用模型/视图(model/view)架构设计。模型用于存放控件的数据,视图则用于显示编辑数据,而委托则是…

OpenCV实现视频背景提取

在计算机视觉领域,背景减除(Background Subtraction)是一种常用的技术,用于从视频序列中提取前景对象。 背景减除的核心思想是通过建模背景,然后将当前帧与背景模型进行比较,从而分离出前景对象。 OpenCV…

NFS实验配置笔记

NFS NFS服务 nfs,最早是Sun这家公司所发展出来的,它最大的功能就是可以透过网络,让不同的机器,不同的操作系统,进行实现文档的共享。所以你可以简单的将他看做是文件服务器。 实验准备 ①先准备一个服务器端的操作…

C语言【数据结构】:理解什么是数据结构和算法(启航)

引言 启航篇,理解什么是数据结构和算法 在 C 语言编程领域,数据结构和算法是两个核心且紧密相关的概念 一、数据结构 定义 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合(比如数组),它是组织和存储数…

Vue.js 3 的设计思路:从声明式UI到高效渲染机制

目录 一、声明式UI与虚拟DOM的灵活性 二、渲染器:虚拟DOM到真实DOM的桥梁 三、组件的本质与实现 四、编译与运行时的协同优化 五、性能与可维护性的权衡 总结 Vue.js 3 作为新一代前端框架,其设计理念在声明式UI描述、虚拟DOM优化、组件化架构…

深度学习|MAE技术全景图:自监督学习的“掩码魔法“如何重塑AI基础

一、引言:深度学习的困境与自监督的曙光 深度学习(Deep Learning)无疑是当今人工智能领域基础中的基础。从图像识别到自然语言处理(NLP),它在无数任务中展现了卓越性能。例如,在安防监控中&…

深度学习正则化技术之权重衰减法、暂退法(通俗易懂版)

一、影响模型泛性的因素有?什么是正则化技术?有什么用? 通常,影响模型泛化能力的因素有: 可调节参数的个数:可调节的参数过少,会造成模型过于简单,欠拟合;过多&#xf…

爬虫逆向:Unicorn 详细使用指南

文章目录 1. Unicorn 介绍1.1 Unicorn 的特点1.2 Unicorn功能2. 安装 Unicorn2.1 安装 Python 绑定2.2 安装 Unicorn 核心库3. Unicorn 的基本使用3.1 初始化模拟器3.2 映射内存3.3 写入代码3.4 设置寄存器3.5 执行代码3.6 读取寄存器4. Unicorn 的高级功能4.1 钩子函数4.2 异常…

【SpringBoot】实现登录功能

在上一篇博客中,我们讲解了注册页面的实现。在此基础上会跳转到登录页面,今天给大家带来的是使用 SpringBoot,MyBatis,Html,CSS,JavaScript,前后端交互实现一个登录功能。 目录 一、效果 二、…

【小白向】Ubuntu|VMware 新建虚拟机后打开 SSH 服务、在主机上安装vscode并连接、配置 git 的 ssh

常常有人问VMware-Tools装了也复制粘贴不了怎么办,这个东西影响因素太多了,具体解决办法你们可以参考一下:【经验】VMware|虚拟机只能使用鼠标无法使用键盘、装不了或装了VMware-Tools无法复制粘贴的可能解决办法_增强型键盘驱动程…

mingw工具源码编译

ming-w64 mingw编译生成的库,需要mingw的lib文件支持。 https://github.com/mingw-w64/mingw-w64 使用msys2的bash git checkout v8.0.3 ./configure --disable-dependency-tracking --targetx86_64-w64-mingw32 mingw32-make.exe -j4 修改makefile中的make 改成mi…

LSTM方法实践——基于LSTM的汽车销量时序建模与预测分析

Hi,大家好,我是半亩花海。本实验基于汽车销量时序数据,使用LSTM网络(长短期记忆网络)构建时间序列预测模型。通过数据预处理、模型训练与评估等完整流程,验证LSTM在短期时序预测中的有效性。 目录 一、实验…

Stable Diffusion教程|快速入门SD绘画原理与安装

什么是Stable Diffusion,什么是炼丹师?根据市场研究机构预测,到2025年全球AI绘画市场规模将达到100亿美元,其中Stable Diffusion(简称SD)作为一种先进的图像生成技术之一,市场份额也在不断增长&…

Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR

简版 核心流程图 根据,Webpack的构建流程分为初始化、编译和输出三个阶段。初始化阶段读取配置、加载插件、实例化Compiler。编译阶段(构建依赖关系)涉及Compiler类的运行,生成Compilation对象,处理模块依赖。输出阶…

《Transformer如何进行图像分类:从新手到入门》

引言 如果你对人工智能(AI)或深度学习(Deep Learning)感兴趣,可能听说过“Transformer”这个词。它最初在自然语言处理(NLP)领域大放异彩,比如在翻译、聊天机器人和文本生成中表现出…

Java --- 根据身份证号计算年龄

介绍 根据身份证号计算年龄 Java代码 /*** 根据身份证号计算年龄* param birthDateStr* return*/public static int calculateAge(String birthDateStr) {try {birthDateStrbirthDateStr.substring(6,68);// 定义日期格式SimpleDateFormat sdf new SimpleDateFormat("…

零成本搭建Calibre个人数字图书馆支持EPUB MOBI格式远程直读

文章目录 前言1.网络书库软件下载安装2.网络书库服务器设置3.内网穿透工具设置4.公网使用kindle访问内网私人书库 前言 嘿,各位书虫们!今天要给大家安利一个超级炫酷的技能——如何在本地Windows电脑上搭建自己的私人云端书库。亚马逊服务停了&#xff…