上期回顧: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)
---------------------------------------------------------------------------------
關注微信公衆號即可在手機上查閱,並可接收更多測試分享~