一、滑屏操作
不需要看到歡迎頁面,直接做里面的后續操作就好了。也就是我想記住一些用戶的習慣, 不要像第一次訪問一樣,有一個重置與否,給它關閉了。
# 重置與否
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 Android/ target=_blank class=infotextkey>安卓
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、longPress和release組合起來使用的。長按和短按的時間長度不同。
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 在不同的版本修復了不同的問題,但是修復的同時也可能出現不同的問題。