堅持原創輸出,點選藍字關注我吧
作者:清菡
部落格: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、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 在不同的版本修復了不同的問題,但是修復的同時也可能出現不同的問題。
公眾號清菡軟體測試首發,更多原創文章:清菡軟體測試 94+原創文章,歡迎關注、交流,禁止第三方擅自轉載。