坚持原创输出,点击蓝字关注我吧

作者:清菡

博客:oschina、云+社区、知乎等各大平台都有。

目录

  • 一、滑屏操作

    • 1.访问之后,马上就滑屏可以吗?
    • 2.连续实现 2 次滑屏
    • 3.代码
  • 二、模拟触屏
    • 1.短按和点击的区别?
    • 2.用坐标还是元素?
    • 3.引入 TouchAction
    • 4.每个行为函数都有 3 个参数
    • 5.首先确定每一个点的位置
    • 6.代码
  • 三、注意

一、滑屏操作

不需要看到欢迎页面,直接做里面的后续操作就好了。也就是我想记住一些用户的习惯, 不要像第一次访问一样,有一个重置与否,给它关闭了。

# 重置与否
desired_caps["noReset"]=True

1.访问之后,马上就滑屏可以吗?

不可以。先等待首页有个元素出现,再去滑屏。滑屏操作需要时间,模拟器或者真机执行操作更需要时间。如果直接滑动 2 次,第一次滑动效果还没展示出来就直接滑动第二次了,就会看到看不懂得现象。所以这种情况下就要加上time

2.连续实现 2 次滑屏

#从右向左滑
driver.swipe(start_x,start_y,end_x,end_y,200)
time.sleep(1)
driver.swipe(start_x,start_y,end_x,end_y,200)

3.代码

# 微信app 安卓
from appium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.mobileby import MobileBy desired_caps={}
# 平台类型
desired_caps["platformName"]="Android"
# 平台版本号
desired_caps["platformVersion"]="7.0"
# 设备名称
desired_caps["deviceName"]="XPUDU17713003790"
# app 包名
desired_caps["appPackage"]="com.tencent.mm"
# app 入口 acitivity
desired_caps["appActivity"]="com.tencent.mm.ui.LauncherUI"
# 重置与否
desired_caps["noReset"]=True # aapt dump badging 包名
# 连接Appium server。前提:appium desktop要启动。有监听端口。
# 将desired_caps发送给appium server。打开app
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps) # ANDROID_UIAUTOMATOR 这个是一种定位表达式,用其它的表达式也是可以的。
loc=(MobileBy.ANDROID_UIAUTOMATOR,'new UiSelector().text("通讯录")')
WebDriverWait(driver,30).until(EC.visibility_of_element_located(loc)) #height、width
size= driver.get_window_size()
start_x=size['width']*0.9
start_y=size['height']*0.5 end_x=size["width"]*0.1
end_y=size['height']*0.5 #从右向左滑
# 时间长短需要根据实际情况自己来调试,避免没滑过去,代码就执行完毕了。
driver.swipe(start_x,start_y,end_x,end_y,300)
time.sleep(2)
driver.swipe(start_x,start_y,end_x,end_y,300)

二、模拟触屏

滑屏也是触屏实现的。手指在屏幕上点点点,在 Appium 中提供了专门的TouchAction类来做这件事。

Press、longPressrelease组合起来使用的。长按和短按的时间长度不同。

move_to手按住别松开,一直滑动到另外一个点。在每一个操作之间都调用下wait,暂缓下它们的操作间隙,不然太快了,看起来就是一团乱麻。

1.短按和点击的区别?

短按是按住不松开,但是时间比较短。tap是点完就松开,不需要组合别的一起用。有Press就必须有release,不然就一直按着上面动都不动了。

发送命令后,只有调用perform才能真的去执行些操作命令,否则是不行的。

将所有的行为按要求放在列表中,可以将列表中所有的东西取消cancel

滑屏操作是在屏幕上按住一个点,然后滑动到另外一个点,最后把它松掉。

九宫格就是个典型的触屏应用。

2.用坐标还是元素?

元素方便简单,但是不是你想选就一定是哪一种。一种情况,9 个点都是独立的元素,那么用元素就可以了;第二种情况,9 个点都在一个元素里面怎么办?就没有办法实现元素的移动,因为就一个元素。这个时候就必须要用坐标。

坐标需要精确定位。需要思考每个坐标之间的关系。

3.引入 TouchAction

from appium.webdriver.common.touch_action import TouchAction

TouchAction 的源码:

4.每个行为函数都有 3 个参数

swipe滑屏操作是没有元素的,针对的是整个屏幕。屏幕的话就只能通过坐标点。所以你看swipe的源码就可以看到。

看下 swipe 的实现-源码:

  action = TouchAction(self) #首先实例化TouchAction
action \
.press(x=start_x, y=start_y) \
.wait(ms=duration) \
.move_to(x=end_x, y=end_y) \
.release()
action.perform()
return self

现在是它帮你封装好了。实际上不用swipe,就用TouchAction自己去写都可以。

x=end_x, y=end_y,没有用el。

5.首先确定每一个点的位置

选择一个元素上的坐标,大概会选哪个位置的?

中心。

坐标轴写错了一点,偏移了点,好歹也是在范围之内。如果选择边缘的点,偏了点可能就出不去了。所以,一般选一个元素的坐标,尽量选择中心。 每个点之间的间隔是一样的。从一个点挪到另外一个点,y 轴不用动,x 轴只要有个固定的距离就好了。

例如 3 个点的值是:147.376、359.378、571.378

能把这 3 个值直接这样写出来吗?

不能。换台设备就不行了,这样绝对的数据是不能放在这里的。采用和滑屏操作一样的思想,用百分比和相对距离。如果能获取到元素的大小以及起点坐标就可以了。

距离是 59。147-59=88

可以估算一下:

如果是长方形那就需要另外再算,但是图中是正方形,这 9 个格子的间距是没有什么区别的,重点是它与边界值的差距。

边界值的差距是多少?

把它分成 6 份。第一个点的坐标:能够得到 view 的起点坐标是 45,272。有专门的函数可以获取元素的大小以及它的起点坐标。

假设起点坐标是 x、y,我现在已经知道将它分成了 6 份。

那么,第一个点的坐标怎么写?

x+width*1/6 + height*1/6

看 size 源码:

看 location 源码:

#元素的大小
size=ele.size
# 均分的步长 高和宽一样(因为是正方形)
step=size["width"]/6#py3中除是取整数的,会缺点小数点没关系。取得是终点,问题不大,还是可以滑动到的。
# 元素的起点坐标-左上角
ori=ele.location
point1=(ori["x"]+step,ori["y"]+step)
TouchAction(driver)

等于横向走了这么远,纵向也走了这么远,刚好对着这个点了。

第二个点的坐标怎么算?

基于第一个点的基础上做调整就行了。y 轴不变,x 轴往前走了 2 份。

第3个点也是在第2个点的基础上往前挪动了2个。

#元素的大小
size=ele.size
# 均分的步长 高和宽一样(因为是正方形)
step=size["width"]/6#py3中除是取整数的,会缺点小数点没关系。取得是终点,问题不大,还是可以滑动到的。
# 元素的起点坐标-左上角
ori=ele.location
point1=(ori["x"]+step,ori["y"]+step)
point2=(point1[0]+step*2,point1[1]) #x轴增加了2*step
point3=(point2[0]+step*2,point2[1]) #x轴增加了2*step
TouchAction(driver)

第4个点的坐标:

它是倒着往回走。

第5个点的坐标。

#元素的大小
size=ele.size
# 均分的步长 高和宽一样(因为是正方形)
step=size["width"]/6#py3中除是取整数的,会缺点小数点没关系。取得是终点,问题不大,还是可以滑动到的。
# 元素的起点坐标-左上角
ori=ele.location
point1=(ori["x"]+step,ori["y"]+step)
point2=(point1[0]+step*2,point1[1]) #相对于point1,x轴增加了2*step
point3=(point2[0]+step*2,point2[1]) #相对于point2,x轴增加了2*step
point4=(point3[0]-step*2,point3[1]+step*2)#相对于point3,x轴减少了2*step,y轴增加了2*step
point5=(point4[0],point4[1]+step*2)#相对于point4,x轴不变,y轴增加了2*step
TouchAction(driver).press(x=point1[0],y=point1[1]).wait(200).\
move_to(x=point2[0],y=point2[1]).wait(200).\
move_to(x=point3[0],y=point3[1]).wait(200).\
move_to(x=point4[0],y=point4[1]).wait(200).\
move_to(x=point5[0],y=point5[1]).wait(200).\
release().\
perform() #.\是换行用的。

以 1 个点做基准,针对不同的点做基准,容易把自己绕晕了。所以,都以前一个点做基准。也可以以起点作为基准。

6.代码


from appium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.mobileby import MobileBy
import time
from appium.webdriver.common.touch_action import TouchAction desired_caps={}
# 平台类型
desired_caps["platformName"]="Android"
# 平台版本号
desired_caps["platformVersion"]="7.0"
# 设备名称
desired_caps["deviceName"]="XPUDU17713003790"
# app 包名
desired_caps["appPackage"]="填上appPackage"
# app 入口 acitivity
desired_caps["appActivity"]="填上appActivity"
# 重置与否
desired_caps["noReset"]=True # 连接Appium server。前提:appium desktop要启动。有监听端口。
# 将desired_caps发送给appium server。打开app
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps) ele=driver.find_element_by_id("填上元素定位下吧,如果你app这里的元素定位不了,那就只能用坐标了,需要另外学习这块的坐标怎么写,呜呜")
# 元素的大小
size=ele.size
# 均分的步长 高和宽一样(因为是正方形)
step=size["width"]/6#py3中除是取整数的,会缺点小数点没关系。取得是终点,问题不大,还是可以滑动到的。 # 元素的起点坐标-左上角
ori=ele.location
point1=(ori["x"]+step,ori["y"]+step)
point2=(point1[0]+step*2,point1[1]) #相对于point1,x轴增加了2*step
point3=(point2[0]+step*2,point2[1]) #相对于point2,x轴增加了2*step
point4=(point3[0]-step*2,point3[1]+step*2)#相对于point3,x轴减少了2*step,y轴增加了2*step
point5=(point4[0],point4[1]+step*2)#相对于point4,x轴不变,y轴增加了2*step
TouchAction(driver).press(x=point1[0],y=point1[1]).wait(100).\
move_to(x=point2[0],y=point2[1]).wait(100).\
move_to(x=point3[0],y=point3[1]).wait(100).\
move_to(x=point4[0],y=point4[1]).wait(100).\
move_to(x=point5[0],y=point5[1]).wait(100).\
release().\
perform() #.\是换行用的。

三、注意

这里是 V1.6.几的或 V1.7.1,V1.7 以前的,如果按上面代码的方式写坐标的话,会报错“提示越界了”这个是版本差异引起的。 需要看日志,日志中会告诉你,当前滑动的点是什么。

多看Appium中的日志,它会问你是el滑动还是坐标滑动?

坐标滑动会直接打印坐标值,看下坐标值超了就说明是有问题的。版本比较晚的应该都是绝对坐标。

实际上是不会“越界”的,那只因为用的相对距离来滑动的。move_to的每一个坐标点都是真实的绝对坐标。

用的当前元素的原坐标点加上移动的距离得到的是当前相对于整个屏幕左上角这个 00 的真实坐标值。

我现在用的坐标,但是有的版本的问题是:

它的move_to参数不是绝对坐标。而是相对于上一个点的移动距离。

比如第一个点,press 是没有错的。用 move_to 的时候 y 没有动,x 轴移动了 2 倍 step。

如果是这种相对距离移动的话,要求x=2*step,没有坐标,y=0。如果不是按这种风格写的,会报“越界”

它拿着上一个点的坐标值加上 x,y,得出来肯定超界了。因为代码里写的真实坐标,再加上 x,第二个点可能没有越界,第三个点就越界了。

如果报“越界”错误,那么就改成相对坐标滑动一下,看看有没有报错。

Appium 在不同的版本修复了不同的问题,但是修复的同时也可能出现不同的问题。


公众号清菡软件测试首发,更多原创文章:清菡软件测试 94+原创文章,欢迎关注、交流,禁止第三方擅自转载。

Appium常用操作之「微信滑屏、触屏操作」的更多相关文章

  1. 「微信小程序免费辅导教程」26,基础内容组件rich-text体验

  2. 「微信小程序免费辅导教程」25,基本内容组件text的使用及个人帐号允许的服务类目

  3. 「微信小程序免费辅导教程」24,基础内容组件icon的使用探索与7月26日微信公众平台的更新解读

  4. WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果

    原文:WPF技术触屏上的应用系列(五): 图片列表异步加载.手指进行缩小.放大.拖动 .惯性滑入滑出等效果 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统, ...

  5. WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现

    原文:WPF技术触屏上的应用系列(六): 视觉冲击.超炫系统主界面.系统入口效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体 ...

  6. WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现

    原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...

  7. WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放、播放、暂停、可拖动播放进度效果实现

    原文:WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放.播放.暂停.可拖动播放进度效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,5 ...

  8. WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现

    原文:WPF技术触屏上的应用系列(一): 3D 图片(照片)墙.柱面墙(凹面墙或者叫远景墙.凸面墙或者叫近景墙)实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...

  9. WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现

    原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系 ...

随机推荐

  1. 与Bat脚本的故事

    因为工作时需要将定时处理的业务抽出来,废弃通过监听定时调用的这种方法,改为通过第三方软件定时执行bat脚本来实现,所以学习了一下bat脚本,整理出一些学习中的基础点和重点. 基础点: (1)bat脚本 ...

  2. Python-面向网络编程-socket原理

    socket 整个计算机网络是由协议构成,想要通信必须遵守对应的协议,如Web中的http协议.传输协议TCP和UDP等等.在网络工程师的眼中,可能现在网络上的一切都是socket,一切皆socket ...

  3. K8S环境的Jenkin性能问题处理

    环境信息 在K8S环境通过helm部署了Jenkins(namespace为helm-jenkins),用于日常Java项目构建: kubernetes:1.15 jenkins:2.190.2 he ...

  4. 读书笔记——Effective C++

    1.让自己习惯C++ 条款01:视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 条款02:尽量以const.enum.inline替换 #define 对于单纯 ...

  5. 用于ASP.net的MVC模块

    下载MVCBricks_SRC - 492.58 KB 表的内容 介绍系统要求游戏闪屏的最终考虑历史 介绍 自从我写上一篇关于ASP的文章以来,已经有很长时间了.净的话题.这次我决定写一些关于它的东西 ...

  6. shell-添加条件测试的多种方法语法介绍与简单实战

    1. 条件测试  1) 测试语句 1) 条件测试语法 在bash的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同的操作,有时也会通过与if等条件语句相结合,使我们可以方便的完成判断. ...

  7. docker-compose应用

    docker-compose应用 需求编写compose模板文件,实现同时启动tomcat.mysql.redis容器. 1.编写模板文件 #新建文件夹mkdir -p /tzh/compose_te ...

  8. vue 项目打包后静态资源加载不到

    1, 2,

  9. k8s集群,使用pvc方式实现数据持久化存储

    环境: 系统 华为openEulerOS(CentOS7) k8s版本 1.17.3 master 192.168.1.244 node1 192.168.1.245 介绍: 在Kubernetes中 ...

  10. vmware 安装tools

    kali linux 更换成国内源后 安装tools命令 apt install open-vm-tools-desktop fuse -y 需重启  reboot