基於airtest的安卓ui自動化實踐

在tester home上初識airtest感覺很驚豔,最近想給組裏的同學分享一下,仔細研究了一番。分享之後,發現他們練習做的還很不錯。

莫非我真的有教書育人的能力?(天真臉)

分爲四個部分講解:airtest簡介,airtest安卓上的應用(分airtest和poco),參考示例,ui自動化方案。

airtest簡介

  • 網易內部工具團隊研發
  • 跨平臺ui自動化框架,適用遊戲與app
  • 基於圖像識別和poco控件識別

支持

  • web
  • windows
  • android
  • ios
  • 遊戲

airtest在安卓上的應用

1.連接

airtest與手機連接有三種方式:USB,無線連接,代碼連接

無線連接的步驟:

1.手機通過usb連接電腦,查看手機ipadb shell ifconfig wlan0 或者直接在手機上看

2.指定tcpip端口號:  adb tcpip 端口號 (端口號可隨便定義,不衝突就行)

3.拔掉手機usb連接

4.cmd命令行輸入:adb connect 手機ip:端口號(剛纔指定)

5.連接成功後,可輸入adb devices 查看到

6.airtest ide右側遠程連接中輸入 adb connect 手機ip:端口號 ,然後在設備列表中,點擊connect

代碼連接的格式:

格式:connect_device("Android://")

括號中格式:Android://adbhost:adbport/serialno

如:connect_device("Android://127.0.0.1:5037/c78886cd")

2.airtest-android的常用方法

1)獲取apk 包名

adb shell  或者 adb –s  設備號(通過adb devices可以看到的) shell

pm list packages

加過濾 pm list packages |grep ala

2)打開apk

start_app('package_name')

3)關閉apk

stop_app('package_name')

4)touch

按壓,對象可以是圖片或者座標,參數可根據需要修改,默認一次,相當於點擊

5)wait

對象是圖片,等待某圖片出現。找到圖片則返回圖片中心點座標,否則超時後拋出異常

6)swip

滑動,對象爲兩個,分別是滑動起點和重點的圖片或座標,或者選用參數VECTOR

7)exists

對象是圖片,判斷圖片是否存在,存在則返回圖片中心點座標,否則返回False

8)text

文本輸入

9)keyevent(這個是需要注意下的)

輸入,需要按下的鍵盤內容,與adb shell input keyevent的值一致

如:keyevent(“KEYCODE_3”) 輸入數字3

https://blog.csdn.net/chen825919148/article/details/18732041

10)snapshot 截圖

11)sleep

延遲時間,默認1秒

12)assert_exists

對象爲圖片,判定圖片存在,如果存在則返回圖片中心點座標,否則拋出異常

13)assert_not_exists

判定圖片不存在,斷言失敗時拋出異常

14)assert_equal

斷言兩個值相同

15)assert_not_equal

斷言兩個值不相同

以上的這部分是圖形識別airtest的部分,下面部分是poco-android部分

 

POCO

 

1.Poco是一款基於UI控件搜索的自動化框架,與基於圖像識別的Airtest不同的是

Poco可以使用類似 poco("OK").click() 的方式來獲取並操作節點

 

2. Poco在大多數平臺中,需要 事先接入Poco-SDK纔可正常使用 ,在少數平臺

Android原生APP)可直接使用Poco,目前支持平臺如下:

POCO-ANDROID如何使用?

1.Poco輔助窗選擇android

2.彈框提示,選擇yes

 

from poco.drivers.android.uiautomation import AndroidUiautomationPoco

poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

3.抓取控件

 

4.自動生成的語句可能效果並不太理想,通常情況下,我們需要編寫一些更復雜

語句、以及更精確的UI控件選擇語句。

AirtestIDE中,我們可以通過暫停功能,凍結當前的UI樹形結構來精確地檢視UI控件;

雙擊UI樹上的節點能自動插入Poco語句,對它們進行更精確的調整可以進一步提升我們腳本的可讀性和運行成功率

 

POCO-ANDROID-UI選擇對象

1.基本選擇器

poco實例後加一對括號就可以進行UI選擇了。選擇器會遍歷所有UI,將滿足給定條件的UI

選出來並返回

 

通過節點名字選擇

poco("android.widget.ImageView")

 

通過名字與屬性選擇(官網複製Unity3D

 

poco('bg_mission', type='Button')

poco(textMatches='^據點.*$', type='Button', enable=True)

2.相對選擇器

直接用節點屬性沒法選出你所想要的UI時,還可以通過UI之間的渲染層級關係進行選擇,例如

父子關係、兄弟關係、祖先後代關係。官網上的截圖,這裏補充下兄弟選擇是sibling,直系是child,其餘是後臺offspring

poco('main_node').child('list_item').offspring('item')

3.空間順序選擇器

按照序號進行選擇總是根據空間排布順序,先從左到右,再一行一行從上到下。

dl = poco("com.alashow.live:id/rv_video").offspring("android.view.ViewGroup")   #這裏是一個list,視頻列表

dl[1].click()

4.迭代一組對象(還是上面那個視頻列表)

dl = poco("com.alashow.live:id/rv_video").offspring("android.view.ViewGroup")

 

for i in dl:

    i.click()

    sleep()

    poco("com.alashow.live:id/iv_back").click()

 

POCO-ANDROID操作UI對象的方法

其實與airtest的方法是相似的,只不過前面需要加上poco對象

可參考官方文檔:

官方文檔:https://poco-chinese.readthedocs.io/zh_CN/latest/source/README.html#tutorials-and-examples

1.Click

poco(text="首頁").click()

 

2.Swipe

joystick = poco('movetouch_panel').child('point_img')

joystick.swipe('up')

joystick.swipe([0.2, -0.2])   正負代表方向,數值代表幅度

 

3. Drag_to

swipe 不同的是, darg 是從一個UI拖到另一個UI,而 swipe 是將一個UI朝某個方向拖動。

下面例子展示如何使用 drag_to 方法

poco(text='突破芯片').drag_to(poco(text='岩石司康餅'))

 

4.局部定位

所有UI相關的操作都默認以UIanchorPoint 爲操作點,如果想自定義一個點那麼可以使用

focus 方法。可參考官方文檔:座標系與度量空間

scrollView = poco(type='ScollView')

scrollView.focus([0.5, 0.8]).drag_to(scrollView.focus([0.5, 0.2]))

5.Wait

在給定時間內等待一個UI出現並返回這個UI,如果已經存在畫面中了那就直接返回這個UI

如果超時了還沒有出現,同樣也會返回,但是調用這個UI的操作時會報錯

類似的操作還有,見 wait_for_appearance

poco('bg_mission').wait(5).click() # wait 5 seconds at mostclick once the object appears

poco('bg_mission').wait(5).exists() # wait 5 seconds at mostreturn Exists or Not Exists

參考示例

1.編寫ui自動化腳本時,應保證打開app和關閉app成對使用,這樣不會對下一個腳本

產生影響

start_app('com.alashow.live')

 

 

stop_app('com.alashow.live')

2.未登錄時,打開直播app後,有可能進入兩個頁面之一:1)直播首頁  2)登錄頁 

如何根據進入的不同頁面進行相應操作

可觀察頁面特徵,如果底部狀態欄存在就是進入了直播首頁,

執行操作點擊我的,進入登錄頁,執行後續操作

可以直接使用airtest腳本實現不解釋,原理一樣poco實現如下

tmp = poco("com.alashow.live:id/view_bottom_bar").exists()

if tmp:

    poco("com.alashow.live:id/view_tab_me").click()

3.執行操作驗證結果

如執行搜索主播的操作,對結果進行校驗

對結果的驗證,可以有兩種方式

1.根據封面對某個主播進行驗證,利用assert_exists

2.判斷搜索出的主播中是否包含搜索的字

第二種方法略微麻煩一點,需結合循環,滑動驗證

poco(“com.alashow.live:id/iv_live_rank”).sibling(“android.widget.ImageView”).click()   #點擊搜索按鈕

poco(“com.alashow.live:id/search_src_text”).click()   #在搜索欄點擊

text(“”)  #輸入需要搜索的

sleep(3)

#判斷沒有更多主播啦字樣出現

 

tmp = False

while not tmp:

    livelist = poco(“com.alashow.live:id/rv_live_search”).offspring(“com.alashow.live:id/tv_user_name”)  #搜索結果直播間列表

    for i in livelist:                      #搜索結果中主播直播間列表

        name = i.get_text()         #獲得主播的暱稱

        if in name:   #判斷在暱稱中則正確

            assert_equal(True, True, "名字裏含有喵.")

        else: #如果不在暱稱中卻搜索出來則不正確

            assert_equal(False, True, 名字裏出現了不含有喵的結果.")

   

    flag = poco(“com.alashow.live:id/rv_live_search”).sibling(“android.widget.TextView”).exists() #判斷底部控件

    if flag:

        tips = poco("com.alashow.live:id/rv_live_search").sibling("android.widget.TextView").get_text()

        if 沒有更多主in tips:  #如果是沒有更多主播啦則結束

            tmp = True

    poco("com.alashow.live:id/rv_live_search").swipe([0,-0.6])

    sleep(2)

4.驗證數值的正確性

送禮後驗證1.送禮跑道,2.送禮後扣費

start_app('com.alashow.live')
sleep(10)

#驗證送禮
#獲得直播間列表
liveroom = poco("com.alashow.live:id/rv_live_home").child("android.widget.FrameLayout")
#選擇第一個直播間進入,直播間需要判斷是開播狀態,還是休息中
state = liveroom[0].offspring("com.alashow.live:id/tv_sentiment").get_text()
if state == "休息中":
    liveroom[0].click()
    sleep()
    poco("com.alashow.live:id/tv_live_remain").click()
else:
    liveroom[0].click()
sleep(2)
#打開禮物面板
poco("com.alashow.live:id/iv_live_gift").click()
#選擇禮物
poco("android.support.v7.widget.RecyclerView").child("com.alashow.live:id/cl_gift_bg")[0].click()
giftprice = poco("android.support.v7.widget.RecyclerView").offspring("com.alashow.live:id/tv_gift_gold").get_text()
goldnum = poco("com.alashow.live:id/tv_gold_num").get_text()
remaingold = str(int(goldnum) - int(giftprice))
print(remaingold)
#送禮
poco("com.alashow.live:id/tv_gift_send").click()

#驗證1送禮出現跑道(從airtest裏面複製到這裏後就變代碼了)
wait(Template(r"tpl1557971798350.png", record_pos=(-0.06, 0.005), resolution=(1080, 2248)))


#驗證2金錢計算
#獲取當前的金錢
goldnum2 = poco("com.alashow.live:id/tv_gold_num").get_text()
#將當前金錢與送禮後的金錢對比,如果相同則通過
assert_equal(goldnum2, remaingold, "送禮扣錢正確.")


sleep(5)
stop_app('com.alashow.live')
 

 

UI自動化編寫規範(純屬個人瞎編,不喜勿噴)

1.保證操作前與操作後不會對後續產生影響

如(編寫前應先思考):

start_app('com.alashow.live')

stop_app('com.alashow.live')

 

2.Airtestpoco 都可以使用,看個人習慣,應養成寫註釋的習慣

如:此腳本的用途,目的(這裏需要進行斷言,會體現到測試報告中)

常用:

Waitassert_existsassert_not_existsassert_equalassert_not_equal

 

3.使用poco編寫腳本時,儘量學會優化腳本(建立在看懂控件樹的基礎上)

如:

poco("android.widget.LinearLayout").offspring("android:id/content").offspring("com.alashow.live:id/content").

child("android.widget.FrameLayout").child("com.alashow.live:id/view_pager").child("android.view.ViewGroup").o

ffspring("com.alashow.live:id/fl_content").offspring("com.alashow.live:id/refresh").

offspring("com.alashow.live:id/rv_live_home").child("android.widget.FrameLayout")[0].

child("android.view.ViewGroup").click()

可簡化爲:

poco("com.alashow.live:id/rv_live_home").child("android.widget.FrameLayout").click()

 

4.一份自動化的腳本儘量保證只驗證一個功能

 

5.利用自動化腳本做UI遍歷(驗證流程)時,應對過程中的數據(如圖片或者數值)進行驗證

 

6.涉及到一個操作出現多種可能的情況時,應使用判斷校驗

如:之前例子中的打開app,出現在登錄頁或者首頁的現象

 

7.建議書寫自動化腳本之前,先畫好(隨便什麼方式能看懂就行)一個流程,以及需要驗證的東東

 

8. 想到什麼再說吧!

 

寫在尾聲:

單個自動化的用例會編寫了,那如何集成到一起呢?難不成我跑用例的時候要一個一個手動跑。

請參考https://blog.csdn.net/u010127154/article/details/83375659

可以實現統一管理用例,輸出報告

哈哈,寫的有點亂,原本寫在ppt裏面的,懶得重新整理啦

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章