Airtest API精講之連續滑動swipe_along()
以下基於
python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83
上期我們講了swipe(),可以從一個圖片或座標滑動到另一個圖片或座標,簡單講就是一個點到另一個點的滑動,那麼多個點的滑動怎麼操作呢?最典型的就是9宮格解鎖,可以通過swipe_along()來實現。
老規矩開場白,我們今天要講的是Airtest框架的swipe_along(),不是Poco框架的,一般我們說Airtest,其實應該指的是Airtest Project,具體這些概念的關係是什麼,可以看之前文章:Airtest Project——UI自動化利器介紹
首先說明一點,某些模擬器如果你選擇的連線引數中有"Use Adb Touch",可能將無法使用swipe_along(),不行就換真機吧。
原始碼解析
我們先來看下swipe_along()的原始碼(不想看原始碼的可以直接跳到後面的演示例項):
1#檔案位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2
3defswipe_along(self,coordinates_list,duration=0.8,steps=5):
4"""
5Performswipeeventacrossmultiplepointsinsequence.
6
7Args:
8coordinates_list:listofcoordinates:[(x1,y1),(x2,y2),(x3,y3)]
9duration:timeintervalforswipeduration,defaultis0.8
10steps:sizeofswipestep,defaultis5
11
12Returns:
13None
14
15"""
16tuple_from_xy=coordinates_list[0]
17swipe_events=[DownEvent(tuple_from_xy,pressure=self.default_pressure),SleepEvent(0.1)]
18fortuple_to_xyincoordinates_list[1:]:
19swipe_events+=self.__swipe_move(tuple_from_xy,tuple_to_xy,duration=duration,steps=steps)
20tuple_from_xy=tuple_to_xy
21
22swipe_events.append(UpEvent())
23self.perform(swipe_events)
引數:
coordinates_list:座標列表,如[[10,20],[20,20],[30,20]]
duration:執行每2個點之間的等待時間,預設0.8秒
steps:執行每2個點之間的執行步數,預設5
第16行tuple_from_xy = coordinates_list[0]
將座標列表中的第一個座標賦值給tuple_from_xy
,意為起點
第17行:
swipe_events = [DownEvent(tuple_from_xy, pressure=self.default_pressure), SleepEvent(0.1)]
定義了一個滑動事件列表swipe_events
,並向列表中加入了2個事件:起點的按下事件,0.1秒的等待事件
第18-20行,從座標列表的第2個座標開始,迴圈給滑動事件列表swipe_events
追加每2個相臨座標之間的移動事件
第22行swipe_events.append(UpEvent())
給滑動事件列表swipe_events
追加一個抬起事件
第23行self.perform(swipe_events)
將滑動事件列表中的每個事件依次執行
再來看下swipe_along()第19行中self.__swipe_move()移動事件的詳細實現:
1#檔案位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2def__swipe_move(self,tuple_from_xy,tuple_to_xy,duration=0.8,steps=5):
3"""
4Returnasequenceofswipemotionevents(onlyMoveEvent)
5
6minitouchprotocolexample::
7
8d00050
9c
10m020050
11c
12m040050
13c
14m060050
15c
16m080050
17c
18m0100050
19c
20u0
21c
22
23Args:
24tuple_from_xy:startpoint
25tuple_to_xy:endpoint
26duration:timeintervalforswipeduration,defaultis0.8
27steps:sizeofswipestep,defaultis5
28
29Returns:
30[MoveEvent(from_x,from_y),...,MoveEvent(to_x,to_y)]
31"""
32from_x,from_y=tuple_from_xy
33to_x,to_y=tuple_to_xy
34
35ret=[]
36interval=float(duration)/(steps+1)
37
38foriinrange(1,steps):
39ret.append(MoveEvent((from_x+(to_x-from_x)*i/steps,
40from_y+(to_y-from_y)*i/steps)))
41ret.append(SleepEvent(interval))
42ret+=[MoveEvent((to_x,to_y),pressure=self.default_pressure),SleepEvent(interval)]
43returnret
第36行interval = float(duration) / (steps + 1)
2個座標之間的總等待時間/步數+1
第39行,因為把2個座標分成了steps步,所以這裡相當於把2個座標之間的移動,又分成了steps-1次移動,將依次新增每一個小步的移動事件
第41行ret.append(SleepEvent(interval))
,同上,因為把2個座標之間的移動,又分了成steps-1次,所以等待時間也要均分,並新增均分後時間的等待事件
第42行,新增終點座標的滑動事件和等待事件
第43行return ret
將整個移動事件列表返回
繼續看下swipe_along()第23行中self.perform()執行方法的詳細實現:
1#檔案位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2defperform(self,motion_events,interval=0.01):
3"""
4Performasequenceofmotioneventsincluding:UpEvent,DownEvent,MoveEvent,SleepEvent
5
6Args:
7motion_events:alistofMotionEventinstances
8interval:minimumintervalbetweenevents
9
10Returns:
11None
12"""
13foreventinmotion_events:
14ifisinstance(event,SleepEvent):
15time.sleep(event.seconds)
16else:
17cmd=event.getcmd(transform=self.transform_xy)
18self.handle(cmd)
19time.sleep(interval)
大致邏輯就是迴圈判斷滑動事件列表,如果是SleepEvent類就等待相應時間,否則就執行具體類中的getcmd()方法。
那除了SleepEvent類,通過上面幾個方法的原始碼可以看到,還有DownEvent、UpEvent、MoveEvent三個類,每個類中的getcmd()方法返回了minitouch的協議命令,我們以DownEvent為例看一下:
1#檔案位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
2classDownEvent(MotionEvent):
3def__init__(self,coordinates,contact=0,pressure=50):
4"""
5FingerDownEvent
6:paramcoordinates:fingerdowncoordinatesin(x,y)
7:paramcontact:multi-touchaction,startsfrom0
8:parampressure:touchpressure
9"""
10super(DownEvent,self).__init__()
11self.coordinates=coordinates
12self.contact=contact
13self.pressure=pressure
14
15defgetcmd(self,transform=None):
16iftransform:
17x,y=transform(*self.coordinates)
18else:
19x,y=self.coordinates
20cmd="d{contact}{x}{y}{pressure}\nc\n".format(contact=self.contact,x=x,y=y,pressure=self.pressure)
21returncmd
其中contact為手指的意思,就是第幾根手指,pressure是按壓強度(預設50),填入完整引數後的一個協議示例,手指0在[100,0]以力道50按下:
1d0100050
2c
演示例項
畫一個四邊形
先分別在手機上取四個點,不會的可以看之前的文章AirtestIDE基本功能(二)中的Device欄。
然後編寫指令碼:
1#-*-encoding=utf8-*-
2__author__="測試工程師小站"
3
4fromairtest.core.apiimport*
5
6dev=device()#獲取當前手機裝置
7#依次滑過四個座標,每2個座標之間間隔3秒,分3小步
8dev.touch_proxy.swipe_along([[250,819],[738,824],[744,1312],[248,1312],[250,819]],duration=3,steps=3)
我用的畫板App會自動處理為圓角
可以看到每個邊是分為3步,每一步間隔1秒,是不是對duration=3, steps=3這兩個引數有了直觀的理解。四邊形會畫了,圓形、三角形還是問題嗎?
解鎖九宮格
1#-*-encoding=utf8-*-
2__author__="測試工程師小站"
3
4fromairtest.core.apiimport*
5
6#獲取當前手機裝置
7dev=device()
8#解鎖九宮格每一步沒必要再拆分,所以steps設為1
9dev.touch_proxy.swipe_along([[246,1186],[547,1182],[537,1470],[540,1768],[835,1772]],duration=1,steps=1)
---------------------------------------------------------------------------------
關注微信公眾號即可在手機上查閱,並可接收更多測試分享~