上期回顾:Airtest API精讲之放大缩小pinch()
以下基于
python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83
老规矩开场白,我们今天要讲的是Airtest框架的内容,不是Poco框架的,一般我们说Airtest,其实应该指的是Airtest Project,具体这些概念的关系是什么,可以看之前文章:Airtest Project——UI自动化利器介绍
之前我们已经陆续讲了:
Airtest API精讲之swipe()
Airtest API精讲之连续滑动swipe_along()
Airtest API精讲之双指滑动two_finger_swipe()
Airtest API精讲之放大缩小pinch()
归根结底,这些都是定义好的一些手势操作。如果你看了之前的源码解析,应该知道其实实现以上手势的基础在底层就是模拟手指按下、滑动、延时、抬起操作。如果你之前玩过按键精灵,相信会更容易理解,原理是一样的。
但是,以上这些操作,在面对一些复杂业务的时候,可能无法实现一些操作,比如MIUI中删除APP,如果你先long_click()长按应用图标,再swipe()到顶部删除图标,中间是会断的。因为long_click()的完整执行过程是按下、延时、抬起,此时再swipe(),因为前面已经抬起,导致删除操作接不上。
再比如MIUI中三指下滑的截图操作,之前的API最多是两指同时操作,不支持三指。
好在Airtest对Android支持自定义手势操作,允许你自己定义一系列操作并执行。
在开始讲自定义手势之前,有必要了解一下其目录结构。还记得之前Airtest的目录结构吗?Airtest框架源码目录结构解析
在your_python_path/core/android/touch_methods/目录下,一共有base_touch、minitouch、maxtouch、touch_proxy四个py文件。
base_touch.py中有BaseTouch类,我们之前讲的4个API均是在这个类中定义。另外有DownEvent、UpEvent、MoveEvent、SleepEvent四个基础类,这四个类共同组成了之前4个API的基础操作。
minitouch.py和maxtouch.py分别有Minitouch和Maxtouch类,其均是继承自BaseTouch类。当你的设备支持openstf的minitouch时则使用minitouch,否则使用maxtouch。maxtouch是Airtest自己开发的。其实这里的结构和Airtest源码分析--Android屏幕截图方式 是非常类似的。
touch_proxy.py中定义了TouchProxy类,它会根据需要自动调用minitouch或maxtouch,所以对于上层是透明的,你不需要关心你用的是minitouch还是maxtouch,你直接执行minitouch或maxtouch中的方法就可以了。
源码解析
我们先来看下DownEvent、UpEvent、MoveEvent、SleepEvent四个基础类的源码(不想看源码的可以直接跳到后面的演示实例):
1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2# 以DownEvent为例
3
4class DownEvent(MotionEvent):
5 def __init__(self, coordinates, contact=0, pressure=50):
6 """
7 Finger Down Event
8 :param coordinates: finger down coordinates in (x, y)
9 :param contact: multi-touch action, starts from 0
10 :param pressure: touch pressure
11 """
12 super(DownEvent, self).__init__()
13 self.coordinates = coordinates
14 self.contact = contact
15 self.pressure = pressure
16
17 def getcmd(self, transform=None):
18 if transform:
19 x, y = transform(*self.coordinates)
20 else:
21 x, y = self.coordinates
22 cmd = "d {contact} {x} {y} {pressure}\nc\n".format(contact=self.contact, x=x, y=y, pressure=self.pressure)
23 return cmd
参数:
coordinates:操作的绝对坐标点
contact: 第X根手指,0是第1根手指(默认值),1是第2根手指……
pressure: 按压力度,默认50
每个类中的getcmd()方法返回了minitouch的协议命令。其中contact为手指的意思,就是第几根手指,pressure是按压强度(默认50),填入完整参数后的一个协议示例,手指0在[100,0]以力道50按下:
1d 0 100 0 50
2c
我们要实现自定义的操作,也是像官方提供的4个API一样,去组合这4个基础操作,比如删除APP的操作,就是DownEvent按下+SleepEvent延时几秒+MoveEvent移到删除图标+UpEvent抬起。把这些操作按顺序放入列表,并使用perform()执行。
我们再看下perform()源码:
1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2 def perform(self, motion_events, interval=0.01):
3 """
4 Perform a sequence of motion events including: UpEvent, DownEvent, MoveEvent, SleepEvent
5
6 Args:
7 motion_events: a list of MotionEvent instances
8 interval: minimum interval between events
9
10 Returns:
11 None
12 """
13 for event in motion_events:
14 if isinstance(event, SleepEvent):
15 time.sleep(event.seconds)
16 else:
17 cmd = event.getcmd(transform=self.transform_xy)
18 self.handle(cmd)
19 time.sleep(interval)
参数:
motion_events:操作列表
interval: 操作间隔,默认0.01秒
大致逻辑就是循环判断传入的事件列表,如果是SleepEvent类就等待相应时间,否则就执行具体类中的getcmd()方法。
演示实例
删除APP自定义手势
1# -*- encoding=utf8 -*-
2__author__ = "测试工程师小站"
3
4from airtest.core.api import *
5from airtest.core.android.touch_methods.base_touch import *
6
7# 获取当前手机设备
8dev = device()
9
10# 定义操作事件列表
11delete_app_event = [
12 DownEvent([908, 892]), # 在应用的坐标上按下手指
13 SleepEvent(2), # 延时2秒
14 MoveEvent([391, 523]), # 移动到中间点
15 SleepEvent(0.5),
16 MoveEvent([165,285]), # 移动到删除应用的垃圾桶坐标
17 SleepEvent(2), # 延时2秒
18 UpEvent() # 抬起手指
19 ]
20
21# 执行操作事件列表
22dev.touch_proxy.perform(delete_app_event)
23
24# 执行完删除APP手势后,再执行一个点击操作点确定即可,这里不再写出
三指滑屏截图自定义手势
1# -*- encoding=utf8 -*-
2__author__ = "测试工程师小站"
3
4from airtest.core.api import *
5from airtest.core.android.touch_methods.base_touch import *
6
7# 获取当前手机设备
8dev = device()
9
10# 定义三指起始点
11finger1, finger2, finger3 = [228, 388],[528, 388],[828, 388]
12
13# 定义操作事件列表
14snapshot_event = [
15 DownEvent(finger1, 0), # 按下手指1
16 DownEvent(finger2, 1), # 按下手指2
17 DownEvent(finger3, 2), # 按下手指3
18 SleepEvent(0.1), # 延时0.1秒
19 ]
20
21# 我们模拟三根手指滑动3次后到手机底部
22for i in range(1,4):
23 node1 = [finger1[0],finger1[1]+500*i] # 定义手指1滑动节点
24 node2 = [finger2[0],finger3[1]+500*i] # 定义手指2滑动节点
25 node3 = [finger2[0],finger3[1]+500*i] # 定义手指3滑动节点
26 snapshot_event.append(MoveEvent(node1, 0))# 手指1滑动到node1
27 snapshot_event.append(MoveEvent(node2, 1))# 手指2滑动到node2
28 snapshot_event.append(MoveEvent(node3, 2))# 手指3滑动到node3
29 snapshot_event.append(SleepEvent(0.2)) # 延时0.2秒
30
31# 加入三根手指的抬起事件
32snapshot_event.append(UpEvent(0))
33snapshot_event.append(UpEvent(1))
34snapshot_event.append(UpEvent(2))
35
36# 执行操作事件列表
37dev.touch_proxy.perform(snapshot_event)
---------------------------------------------------------------------------------
关注微信公众号即可在手机上查阅,并可接收更多测试分享~