Appium+python自动化(十一)- 元素定位- 下卷超详解)

1、 List定位

  List故名思义就是一个列表,在python里面也有list这一个说法,如果你不是很理解什么是list,这里暂且理解为一个数组或者说一个集合。首先一个list是一个集合,那么他的个数也就成了不确定性,所以这里需要用复数,所以在我们定位时我们不能够接着用find_element_by_id等等定位方式了,我们需要用他的复数形式find_elements_by_id,所有的定位方式都一样需要采用复数加s。这里我们接着上篇的案例讲,如何使用list定位想定位的元素。首先看一下图片:

我们查看图片可以知道我们能够很轻松的通过id定位到整个祖父节点,我们接下来需要做的事定位这个祖父节点下所有的“android.widget.RelativeLayout”父节点,同样的首先我们看一张图:

这里我们需要直接使用定位复数的方法来操作,直接看代码(祖父节点定位到父节点):

element= driver.find_element_by_id("com.taobao.taobao:id/rv_main_container")
elements = element.find_elements_by_class_name("android.widget.FrameLayout")

通过上面的代码我们直接定位了com.taobao.taobao:id/rv_main_container父节点下的所有android.widget.FrameLayout子节点,但是由于这个android.widget.FrameLayout子节点下边还有许多相同的android.widget.LinearLayout孙节点。

这里我们需要直接使用定位复数的方法来操作,直接看代码(父节点定位到孙节点):

1 elements = element.find_elements_by_class_name("android.widget.FrameLayout")
2 elements1 = elements[1].find_elements_by_class_name("android.widget.LinearLayout")

现在我们需要怎么去操作这个子节点了,这里有两种方法:

1、前面我们讲了List你可以理解为一个数组或者一个集合,这里定位的所有子节点最后就成了个list,如果我们要访问这个list里面的某一个元素我们可以像访问数组中的数据一样通过下标访问。最后的代码就是下面这个样子:

1 element= driver.find_element_by_id("com.taobao.taobao:id/rv_main_container")
2 elements = element.find_elements_by_class_name("android.widget.FrameLayout")
3 elements1 = elements[1].find_elements_by_class_name("android.widget.LinearLayout")
4 elements1[1].click()

上面的代码最后的结果是选择了“聚划算”这个标签页面,然后点击进入。

备注:如果初学者不理解是如何通过下标访问的,这里说一下下标是从0开始,如果要访问list i中的第一个元素结果就是i[0],这部分知识可以看一下python基础。

2、如果你要访问List里面的元素,那么我们是否可以通过for循环语句来依次访问呢?这个在自动化中会经常用到。下面你可以通过这个思路自己去实战一下,看能否达到预期效果。下面看我的代码:

1 element= driver.find_element_by_id("com.taobao.taobao:id/rv_main_container")
2 elements = element.find_elements_by_class_name("android.widget.FrameLayout")
3 elements1 = elements[1].find_elements_by_class_name("android.widget.LinearLayout")
4 for ele in elements1:
5     ele.click()

看上面的代码,我们通过循环去访问这个list里面的每一个元素,因为每次循环得到的都是其中一个元素,那么我们只需要在这个元素上加上你想要的操作即可,所以我们这里可以直接点击进去。

如果你动手做到这里会发现一个问题,你进入到第一个标签后没一会儿系统就会报错,为什么呢?你也可以试着去解决这个问题,后面我们会讲解这块儿知识。

2、 内嵌H5定位

2.1 hybrid定位思考

在web自动化中我们会遇见frame的问题,在遇见这些内嵌的标签后我们需要做的就是切换窗口,那么在app自动化测试也有类似的情况就是我们经常看见的内嵌html,在我们原生的app中增加一个由html做成的页面。大家可以思考一下这种情况怎么操作。

2.2 hybrid常见定位问题分析

首先我们看一下下面一张图片:

通过右边的结构图我们能够清晰的看见整个页面就是一个webview,无论从什么角度来定位我们都不能够很好的进行,如果这个时候我们需要操作页面的元素就需要通过切换contexts来完成。但是在讲这个知识点之前大家先按照网上的知识来试一下处理这个页面,看能否成功。下面先说大家会遇见的问题:

1、可能你看到有的文章显示我们不需要通过切换contexts就能够完成定位,这样的情况有,但是那种情况作者只在微博登录、qq登录等第三方登录时遇见过,如果不是这样的情况而像上面的情况就没办法通过类似的方法进行完成,所以我希望读者遇见这种情况时自己动手去操作,看什么方式更加适合自己的项目。

2、需要切换contexts那么就需要获取页面的所有contexts,此时你通过官网或者其他文章的知识通过下面的方法来获取,可能会报错,这种情况关系不大。

1 webview = self.driver.contexts
2 print webview

如果你通过上面的代码来调试但是却报错,但是其他资料却没问题时你也不要着急,这里你需要确定两件事情:(1)、app打包的时候需要开启webview 的debug属性setWebContentDebuggingEnabled(true),这个直接让开发加上就好。一般情况是开启的,毕竟他们也要调试。(2)、你用很多手机去调试,发现有一些可以有一些不可以,但是你用模拟器却都可以,根据官方给出的答案是这个时候你需要去将手机root,然后再试。目前作者遇见了这两种情况,第二种我也是调试了很久才找到原因。

2.3 hybrid定位讲解

这两个问题解决后那么定位webview就轻松搞定,直接看代码:

1 webview = driver.contexts
2 driver.switch_to.context(webview[1])
3 driver.find_element_by_link_text('PHP').click()

对于初学者对于上面的代码可能不是很理解,下面我们看一下日志:

大家这里不用管我执行代码和之前的区别(多了一个self),我们看下面控制台的输出,输出的是一个list,前面说过list和数组类似,在这个list里面有两个元素“NATIVE_APP”,“WEBVIEW_cn_com_open_mooc”,第一个元素是我们原生的app的contexts,后面的则是我们的webview的context,所以我们需要获取webview的context时只需要通过这个list的下表来进行访问。

我们获取到webview的context后只需要通过driver.switch_to.context()进行切换就好。当切换后我们就可以像定位web一样进行定位。

看下面一张图片我们通过浏览器将h5页面打开:

通过上面的图片我们就能够很轻松的像web一样进行定位,也就可以使用web的一些定位方式。看到这里是不是觉得解决了一个难题呢?动手去吧。

2.4 hybrid问题实战

通过前面的学习我相信你已经有了一些实战能力,这里给大家提一个问题,我们获取到的contexts每次一定是两个吗?如果不是两个那么我们上面的脚本是不是就没办法用了呢?可以思考一下这里怎么解决,在看我们下面的思路以及解决方案。

无论在什么页面我们去获取contexts时他无论有几个但是他的类型是不是肯定都是一个list呢?既然是list那么我们是否可以取到里面的每一个值,然后把每一个值进行判断,只要找出我们的webview就可以了呢?下面看代码:

1 #获取当前页面所有的contexts
2 webview = driver.contexts
3 #在获取到的contexts list里面去挨个循环
4 for context in webview:
5   #判断循环中单个的context是否是webview,如果是就进行切换,并且跳出循环
6   if 'WEBVIEW' in context:
7     driver.switch_to.context(context)
8     break
9 driver.find_element_by_link_text('PHP').click()

通过上面的代码我们是否完美的解决了内嵌H5的定位问题呢?动手吧

3、 滑动定位

3.1 滑动定位方式

在app自动化中我们经常会遇见一个问题,我们需要查找的元素不在当前可展示的屏幕,至于在什么地方我们不知道,如果这个时候我们一直使用在当前页面查找,那么系统就会报错,为了解决这个问题我们就需要使用滑动查找。

首先的思路是我们在需要查找对象的页面查找一下该元素,判断该元素是否在当前页面,如果该元素不在该页面那么我们就需要去互动屏幕,到我们的下一屏幕,然后再进行查找,依次类推到找到为止。

3.2 滑动定位思路分析

方式我们有了,那么我们就需要知道实现这个功能应该有哪些点。下面跟着我一起来分析一下:

1、需要查找的元素我们是不是需要知道是什么呢?这个需要先确定

2、我们需要找的页面是在我们的当前页面的上方还是下方还是左方还是右方,我们不能确定,那么我们是否需要确定我们需要滑动的方向?

3、元素和方向有了,但是你知道我们每次需要滑动屏幕的多少吗?那么我们是否需要先去获取屏幕的大小,然后针对不同的方向去计算一个滑动的值呢?

万事具备只欠东风,去按照这个思路动手练习一吧。

3.3 滑动定位实战

一、根据上面的思路我们能首先来确定我们需要查找的元素,看下面图片:

我们要找实战推荐后面的“换一换”按钮,然后进行点击。首先我们查看他的定位信息

最后我们查找元素的定位信息代码如下:

1 self.driver.find_element_by_id('cn.com.open.mooc:id/tv_replace').click()

  对于有一定基础的人可能会觉得这个很low,但是有没有思考过一个问题,我们可以通过这个代码去执行,在没有这按钮的时候却会报错,也就没有办法执行下去了,那么需要怎么处理呢?所以这个时候我们需要有一些python的容错知识,即使我们的代码执行出错了,那么也要让他按照我们的意思执行下去。try.......except.......,这个就是我们python中的容错处理 ,下面我们看添加后的代码:

1 try:
2 self.driver.find_element_by_id('cn.com.open.mooc:id/tv_replace').click()
3 except Exception,e:
4 print e

try的意思就是告诉编译器试着去执行他下面这一段代码,如果报错了,那么你就把except里面的错误信息打印出来。

二、有了元素现在我们需要知道的是不是就是该怎么滑动界面了呢?首先我们看一下下面这张图片:

在我们使用app的过程中存在上面几种滑动情况,我们把整个界面看作为一个坐标系(x,y),如果我们需要往上滑动,那么我们是不是就是x轴不动,y轴从下往上动呢?往下就是x轴不动,y轴从上往下呢?同理左右滑动是不是就是应该y轴不动x轴左右滑动呢?可以好好去体会一下,脑海中有个画面。

在appium中滑动我们所需要使用的方法就是swipe函数,至于往哪个方向滑动就是看我们里面的x,y的值,如果我们需要下往上滑动那么我们就应该是:

1 self.driver.swipe(x1,y1,x1,y2,t)

上面的代码x轴的值不变,y轴的值进行了变化,所以是沿着上下进行滑动的,从y2滑动到了y1点。t代表的是多少时间完成这个动作,或者说这个时间持续多久。

备注:这里需要注意的是屏幕的x,y的值是从左上角开始取的,左上角为(0,0),右下角是最大。

三、上面滑动的方法看着是好用,但是我们不可能每次都去填写一个坐标,那样太low,所以我们需要获取屏幕大小,直接看代码:

1 x = self.driver.get_window_size()['width']
2 y = self.driver.get_window_size()['height']

  上面的代码就是我们获取到的x,y轴。通过思路我们的代码都有了,下面我们要做的就是对原来的代码进行修改,进行一个封装。下面看代码,这个暂时看不懂没关系,到后面我们学了python'基础就能够看懂了。先思路,然后了解。

 1 #获取屏幕大小2          3 def getSize(self):4   x = self.driver.get_window_size()['width']5   y = self.driver.get_window_size()['height']6   return (x,y)7          8          9 #向左滑动
10 def swipeLeft(self,t):
11   l=self.getSize()
12   x1=int(l[0]*0.9)
13   y1=int(l[1]*0.5)
14   x2=int(l[0]*0.1)
15   self.driver.swipe(x1,y1,x2,y1,t)
16                
17 #向右滑动
18 def swipeRight(self,t):
19   l=self.getSize()
20   x1=int(l[0]*0.25)
21   y1=int(l[1]*0.5)
22   x2=int(l[0]*0.75)
23   self.driver.swipe(x1,y1,x2,y1,t)
24                
25 #向上滑动
26 def swipeUp(self,t):
27   l=self.getSize()
28   x1=int(l[0]*0.5)
29   y1=int(l[1]*0.8)
30   y2=int(l[1]*0.4)
31   self.driver.swipe(x1,y1,x1,y2,t)
32   time.sleep(5)
33          
34 #向下滑动
35 def swipeDown(self,t):
36   l=self.getSize()
37   x1=int(l[0]*0.5)
38   y1=int(l[1]*0.25)
39   y2=int(l[1]*0.75)
40   self.driver.swipe(x1,y1,x1,y2,t)
41          
42 #查找元素,没找到滑动
43 def findLocal(self):
44   x = 1
45   while x==1:
46     if self.fact() == 1:
47       self.swipeUp(2000)
48       time.sleep(3)
49       self.fact()
50     else:
51       print "找到了"
52       x=2
53              
54          
55          
56 #递归
57 def fact(self):
58   n =1
59   try:
60     self.driver.find_element_by_id('cn.com.open.mooc:id/tv_replace').click()
61   except Exception,e:
62     return n

  通过查看上面代码的整个逻辑就是1、首先去查找元素,如果找到了我就直接点击。2、如果没有找到元素那么我就往上滑动(这里可以自己选择),滑动后再次进行查找,如果找到就点击,没有找到继续滑动。动手动手,这里知识点很重要!虽然后面会有一些替代方法,但是思路、算法很重要。

4、小结

   好了,元素定位,常见的大致就这些,这个目前就分享到这里吧,以后如果遇到,给小伙伴再补上!!!


              【下面是我整理的2023年最全的软件测试工程师学习知识架构体系图】


一、Python编程入门到精通

二、接口自动化项目实战

三、Web自动化项目实战


四、App自动化项目实战

五、一线大厂简历


六、测试开发DevOps体系

七、常用自动化测试工具


八、JMeter性能测试

九、总结(尾部小惊喜)

生命不息,奋斗不止。每一份努力都不会被辜负,只要坚持不懈,终究会有回报。珍惜时间,追求梦想。不忘初心,砥砺前行。你的未来,由你掌握!

生命短暂,时间宝贵,我们无法预知未来会发生什么,但我们可以掌握当下。珍惜每一天,努力奋斗,让自己变得更加强大和优秀。坚定信念,执着追求,成功终将属于你!

只有不断地挑战自己,才能不断地超越自己。坚持追求梦想,勇敢前行,你就会发现奋斗的过程是如此美好而值得。相信自己,你一定可以做到!

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

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

相关文章

【InsCode Stable Diffusion 美图活动一期】生成着玩

此为内容创作模板,请按照格式补充内容,在发布之前请将不必要的内容删除 一、 Stable Diffusion 模型在线使用地址: https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置: 三、图片生成提示词与反向…

春秋云境—Initial

文章目录 春秋云境—Initial一、前期准备1、靶标介绍2、相关设备 二、WEB渗透1、ThinkPHP RCE(1)、打开网站(2)、检测漏洞 2、蚁剑连接3、sudo提权4、frpc代理5、fsacn扫描 三、后渗透1、信呼OA RCE(1)、1.…

npm安装依赖报错Unexpected token ‘.‘ 处理

1. 问题 在用nvm切换高版本node版本之后npm install安装项目依赖时报错如下: npm ERR! Unexpected token . 日志信息如下: 报错信息量很少,但是跟高版本node环境下安装依赖有关系。 2. 解决思路 安装低版本的node环境运行项目&#xff…

RabbitMQ死信交换机、TTL及延迟队列

一,死信交换机 1,什么是死信交换机 了解死信交换机之前我们先来了解一下什么是死信,当一个队列满足下面的三种情况的时候我们一般称为死信(dead letter): 消费者使用basic.reject或 basic.nack声明消费失…

petalinux 无法通过SDK进行TCF调试

IP地址设置没问题 但是无法进行DEBUG 原因是没有开启debug模式,做下图设置重新编译程序生成BOOT.bin即可

追踪 Kubernetes 中的 DNS 查询

在过去的文章中,我们曾 追踪过 Kubernetes 中的网络数据包,这篇文章将追踪 Kubernetes 中的 DNS 查询。 让我们以在 Pod 中解析 Service 完全限定域名(FQDN) foo.bar.svc.cluster.local 为例。 在开始之前,先回顾下 …

微信小程序的目录解析--【浅入深出系列001外篇】

浅入深出系列总目录在000集 如何0元学微信小程序–【浅入深出系列000】 文章目录 本系列校训学习资源的选择先说总目录经常碰到的文件(目录)最最常见的目录pages次最常用的就是images 目录 操作起来真正的操作 配套资源 本系列校训 用免费公开视频,卷…

串口wifi6+蓝牙二合一系列模块选型参考和外围电路参考设计-WG236/WG237

针对物联网数据传输,智能控制等应用场景研发推出的高集成小尺寸串口WiFi串口蓝牙的二合一组合模块。WiFi符合802.11a/b/g/n无线标准,蓝牙支持低功耗蓝牙V4.2/V5.0 BLE/V2.1和EDR,WiFi部分的接口是UART,蓝牙部分是UART/PCM 接口。模…

3Ds max图文教程:高精度篮球3D建模

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 第 1 步。使用以下设置在顶部视口上创建球体: 第 2 步。将球体转换为可编辑的多边形: 第 3 步。转到 Edge 子对象级别并剪切以下边缘: 第 4 步。选择以下边,然…

什么是 Elasticsearch 索引?

作者:David Brimley 索引这个术语在科技界已经被用满了。 如果你问大多数开发人员什么是索引,他们可能会告诉你索引通常指的是关系数据库 (RDBMS) 中与表关联的数据结构,它提高了数据检索操作的速度。 但什么是 Elasticsearch 索引&#xff…

Stable Diffusion配置要求,显卡推荐

Stable Diffusion 是一款流行的人工智能图像生成器,您可以在自己的 PC 上运行。但是运行Stable Diffusion的最低规格是多少,哪些组件最重要? Stable Diffusion需要什么 PC 硬件? Stable Diffusion最关键的一个组件是显卡 (GPU)。…

基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件

系列文章目录 基于scrcpy的远程调试方案 基于scrcpy的Android群控项目重构 基于scrcpy的Android群控项目重构 进阶版 基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件(视频) 基于scrcpy的Android群控项目重构…

全国节能宣传周丨物通博联智慧能源解决方案助力节能降碳

今年7月10日至16日,为全国第33个节能宣传周。今年全国节能宣传周活动主题是“节能降碳,你我同行”。 全国节能宣传周活动是在1990年国务院第六次节能办公会议上确定的活动周,开展该活动是实施全面节约战略、开展节能降碳宣传教育、推动形成绿…

Vue3组件间的通信方式

目录 1.props父向子组件通信 2.自定义事件 子向父组件通信 3.全局事件总线 4.v-model组件通信(父子组件数据同步) 绑定单个数据同步 绑定多个数据同步 5.useAttrs组件通信 6.ref与$parent ref获取子组件实例对象 $parent获取父组件实例对象 7.p…

postgresql内核分析 spinlock与lwlock原理与实现机制

​专栏内容: postgresql内核源码分析 手写数据库toadb 并发编程 个人主页:我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 概述 在postgresql 中,有大量的并发同步&#xff0…

260道网络安全工程师面试题汇总(附答题解析+配套资料)

由于我之前写了不少网络安全技术相关的文章和回答,不少读者朋友知道我是从事网络安全相关的工作,于是经常有人私信问我: 我刚入门网络安全,该怎么学? 想找网络安全工作,应该要怎么进行技术面试准备&…

Java设计模式-责任链(Chain of Responsibility)模式

介绍 Java责任链(Chain of Responsibility)设计模式是指很多处理对象构成一个链,链中前一个对象指向后一个对象。请求在链中传递,一个请求可以被一个或者多个对象处理。调用方(即客户端)不知道请求会被链中…

【C++】C++11 (3): lambda表达式和包装器

一、lambda表达式 C98中的一个例子 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 #include <algorithm> #include <functional> int main() {int a[] { 4,1,8,5,3,7,0,9,2,6 };// 默认按照小于比较&#xff…

JS、Vue鼠标拖拽

JS代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevic…

使用Linux Deploy搭建服务器(五)Linux Deploy添加自启动(亲测可用)linuxdeploy自动化配置

添加开机自动任务,可以省去开机后手动输入初始化命令的操作 一、方式1 run-parts方式,也就是rc.local的方式(这种方式有时候不生效,按照4中的配置就好了) 1、Linux Deploy配置 1.点击右下角的设置图标进入设置界面 2.划到“初始化”那块,“启用”打上勾 选项“run-p…