Python +Android +uiautomator test 在init中定義的方法
uiautomator
該模塊是android的一個python包裝uiautomator測試框架。它適用於Android 4.1+,只需通過adb連接Android設備,無需在Android設備上安裝任何東西。
從 uiautomator 進口設備的 ð d.screen.on() D(id= “時鍾”)。點擊()
安裝
$ pip install uiautomator
前提條件
- 安裝Android的SDK,並設置
ANDROID_HOME環境以正確的路徑。 - 啟用設備上的ADB設置,並使用USB連接您的Android設備與您的電腦。
導入uiautomator
-
如果
ANDROID_SERIAL在環境中定義的,或只有一個連接的設備:從 uiautomator 進口設備的 ð -
檢索設備對象時,限制序列號
從 uiautomator 進口設備 ð =設備(' 014E05DE0F02000E “) -
speficy在其他計算機上運行的adb服務器主機和端口
雖然亞行支持
-a選項SDK 4.3以來,但現在它有一個bug。在所有接口而不是localhost上啟動adb服務器偵聽的唯一方法是adb -a -P 5037 fork-server server &從 uiautomator 進口設備 ð =設備(' 014E05DE0F02000E ',adb_server_host = “ 192.168.1.68 ”,adb_server_port = 5037)
注:在下面的例子中,我們使用d代表Android設備對象。
目錄
基本API用法
此部分通過一些簡單的示例顯示設備的正常操作。
-
檢索設備信息
d.info
以下是可能的結果:
{ u'displayRotation': 0, u'displaySizeDpY': 640, u'displaySizeDpX': 360, u'currentPackageName': u'com.android.launcher', u'productName': u'takju', u'displayWidth': 720, u'sdkInt': 18, u'displayHeight': 1184, u'naturalOrientation': True }
關鍵事件設備的操作
-
打開/關閉屏幕
#在屏幕上打開 d.screen.on() #關閉屏幕 d.screen.off()替代方法是:
#喚醒設備 d.wakeup() #睡眠設備,一樣關閉屏幕。 d.sleep() -
按硬/軟鍵
#按home鍵 d.press.home() #按返回鍵 d.press.back() #正常的方式按返回鍵 d.press( “回”) #按下鍵碼0×07(0)與元ALT (0X02)上 d.press( 0x的 07, 0X 02) -
目前支持下列鍵:
homebackleftrightupdowncentermenusearchenterdelete(或del)recent(最近的應用程式)volume_upvolume_downvolume_mutecamerapower
你可以找到所有關鍵代碼定義的Android的KeyEvent。
手勢設備的交互
-
單擊屏幕
#點擊(X,Y)在屏幕上 d.click(X,Y) -
長按屏幕
#長按(X,Y)在屏幕上 d.long_click(X,Y) -
滑動
#從(SX,SY)輕掃(EX,EY) d.swipe(SX,SY,EX,EY) #從(SX,SY)輕掃(EX,EY)與10個步驟 d.swipe(SX,SY ,前,安永,步驟= 10) -
拖動
#從(SX,SY)拖動(EX,EY) d.drag(SX,SY,EX,EY) #從(SX,SY)拖動(EX,EY)與10個步驟 d.drag(SX,SY ,前,安永,步驟= 10)
屏幕設備的操作
-
檢索/設置方向
可能的方向是:
natural要么nleft要么lright要么rupsidedown或u(不能設定)
#檢索方向,也可能是“天然”或“左”或“右”或“upsidedown” 方向 = d.orientation #設置定向和凍結旋轉。 #指出:“upsidedown”不能設置到Android 4.3的。 d.orientation = “升” #或“左”的 d.orientation = “ - [R ” #或“右” d.orientation = “ ñ ” #或“自然” -
凍結/取消凍結旋轉
#凍結旋轉 d.freeze_rotation() #取消凍結旋轉 d.freeze_rotation(假) -
截取屏幕截圖
#采取截圖並保存到本地文件“home.png”,直到Android 4.2或不能工作。 d.screenshot( “ home.png ”) -
轉儲窗口層次結構
#轉儲widown層次結構並保存到本地文件“hierarchy.xml” d.dump( “ hierarchy.xml ”) #或獲得回報傾倒內容(Unicode)的。 XML = d.dump() -
打開通知或快速設置
#開放的通知,不能工作,直到Android 4.3的。 d.open.notification() #開啟快速設定,不能工作,直到Android 4.3的。 d.open.quick_settings() -
等待空閑或窗口更新
#等待當前窗口空閑 d.wait.idle() #等待,直到窗口更新事件發生 d.wait.update()
觀察者
你可以注冊守望者執行某些動作時,選擇器不能找到匹配。
-
注冊觀察者
當選擇器找不到匹配項時,uiautomator將運行所有注冊的觀察器。
- 條件匹配時點擊目標
d.watcher( “ AUTO_FC_WHEN_ANR ”)。當(文= “ ANR ”)。當(文= “等待”)\ 。點擊(文字= “強制關閉”) # d.watcher(名)##創建一個新的命名觀察者。 # 。當(條件)##觀察者的UiSelector條件。 # 。點擊(目標)##執行對目標UiSelector點擊動作。- 條件匹配時按鍵
d.watcher( “ AUTO_FC_WHEN_ANR ”)。當(文= “ ANR ”)。當(文= “等待”)\ .press.back.home() #另類的方式來定義它,如下 d.watcher( “ AUTO_FC_WHEN_ANR ”)。當(文= “ ANR ”)。當(文= “等待”)\ 。按(“回”,“家”) # d.watcher(名)##創建一個新的名為守望。# 。當(條件)##觀察者的UiSelector條件。# 。按<鍵名> ...... <鍵名>。()##按下按鍵逐個順序。# Alternavie方式定義按鍵順序是按(<keybname>,...,<鍵名>) -
檢查命名的監視器是否觸發
觸發觀察者,這意味着觀察者運行並且其所有條件都匹配。
d.watcher( “ watcher_name ”).triggered #真在指定守望的情況下觸發,否則為假 -
刪除命名監視器
#刪除觀察者 d.watcher( “ watcher_name ”)上卸下擺臂() -
列出所有觀察者
d.watchers #所有注冊wachers'名稱的列表 -
檢查是否有任何觀察者觸發
d.watchers.triggered # 真正的觸發任何看守的情況下, -
重置所有觸發的觀察者
#重置所有觸發觀察家,在那之后,d.watchers.triggered會是假的。 d.watchers.reset() -
Remvoe觀察者
#刪除所有已注冊的觀察家 d.watchers.remove() #刪除指定的守望者一樣,同樣d.watcher(“watcher_name”)。remove()方法 d.watchers.remove( “ watcher_name ”) -
強制運行所有觀察者
#力量來運行所有注冊的觀察者 d.watchers.run()
處理程序
處理程序的功能與Watcher相同,只是它實現了我們的Android uiautomator。處理程序和觀察程序之間最不同的用法是,處理程序可以使用自定義的回調函數。
高清 fc_close(設備): 如果設備(文= '強制關閉“).exists: 設備(文= '強制關閉”)。點擊() 返回 真 #返回True手段打破處理程序回調函數的循環。 #在處理回調函數反過來 d.handlers.on(fc_close) #關閉句柄回調函數 d.handlers.off(fc_close)
選擇器
選擇器是標識當前窗口中的特定ui對象。
#要入圍對象,文字是“時鍾”和它的類名是“android.widget.TextView' D(文= '時鍾',的className = ' android.widget.TextView ')
選擇器支持以下參數。請參閱UiSelector DOC java的詳細信息。
text,textContains,textMatches,textStartsWithclassName,classNameMatchesdescription,descriptionContains,descriptionMatches,descriptionStartsWithcheckable,checked,clickable,longClickablescrollable,enabled,focusable,focused,selectedpackageName,packageNameMatchesresourceId,resourceIdMatchesindex,instance
子對象和同級UI對象
-
兒童
#得到孩子或孫子 D(的className = “ android.widget.ListView ”).child(文= “藍牙”) -
兄弟
#得到同胞的兄弟姐妹或子女 D(文= “谷歌”).sibling(的className = “ android.widget.ImageView ”) -
子文本或描述或實例
#得到孩子匹配的className =“android.widget.LinearLayout” #而且它或它的子女或孫子包含文本“藍牙” D(的className = “ android.widget.ListView ”, RESOURCEID = “機器人:ID /列表”) \ .child_by_text( “藍牙”,的className = “ android.widget.LinearLayout ”)#允許滾動搜索,獲得子 D(的className = “ android.widget.ListView ”, RESOURCEID = “機器人:ID /列表”)\ 。 child_by_text( “藍牙”, allow_scroll_search = 真, 的className = “ android.widget.LinearLayout ” )-
child_by_description是找到子哪個或哪些是孫子包含指定的描述中,其他是相同的child_by_text。 -
child_by_instance是在其子層次結構中指定實例的任何位置找到具有子UI元素的子項。這是一個沒有可見的意見進行滾動。
詳情請參閱以下鏈接:
- UiScrollable,
getChildByDescription,getChildByText,getChildByInstance - UiCollection,
getChildByDescription,getChildByText,getChildByInstance
上面的方法支持鏈接調用,例如對於下層
< 節點 指數 = “ 0 ” 文本 = “ ” 資源ID = “機器人:ID /列表” 級 = “ android.widget.ListView ” ...> < 節點 指數 = “ 0 ” 文本 = “ WIRELESS & NETWORKS ” 資源-id = “ ” 類 = “ android.widget.TextView ” ... /> < 節點 索引 = “ 1 ” 文本 = “ ” 資源ID = “ ” 類 = “ android.widget.LinearLayout ” ...> < 節點 指數 = “ 1 ” 文本 = “ ” 資源ID = “ ” 級 = “ android.widget.RelativeLayout ” ...> < 節點 指數 = “ 0 ” 文本 = “無線網絡連接” 資源ID = “機器人: ID /標題“ 級 = ” android.widget.TextView “ ... /> </ 節點 > < 節點 指數 = ” 2 “ 文本 = ” ON “ 資源ID = ” com.android.settings:ID / switchWidget “ 類 = “ android.widget.Switch ” ... /> </ 節點 > ... </ 節點 >我們要點擊文本“Wi-Fi”右側的開關打開/打開Wi-Fi。因為有幾個開關,幾乎相同的屬性,所以我們不能使用類似
d(className="android.widget.Switch")選擇的UI對象。相反,我們可以使用下面的代碼來選擇它。D(的className = “ android.widget.ListView ”,RESOURCEID = “機器人:ID /列表”)\ .child_by_text( “無線網絡連接”,的className = “ android.widget.LinearLayout ”)\ .child(的className = “機器人.widget.Switch “)\ 。點擊() -
-
相對位置
此外,我們可以用相對位置的方法來獲取視圖:
left,right,top,bottom。d(A).left(B),意味着在左側選擇B。d(A).right(B),表示選擇A右側的B.d(A).up(B),表示選擇B以上的A.d(A).down(B),表示在A下選擇B.
所以對於上面的情況,我們可以寫代碼:
##選擇的“無線網絡連接”右側的“開關” D(文= “無線網絡連接”).right(的className = “ android.widget.Switch ”)。點擊() -
多個實例
有時,屏幕可能包含多個視圖與相同的例如文本,那么你將不得不使用選擇器中的“實例”屬性,如下所示:
D(文= “新增”,比如= 0) #這意味着一審文本“新增”但是,uiautomator提供了類似的方法來使用它。
#得到的文本意見的計當前屏幕上的“添加新的” D(文= “新增”).Count之間#一樣count屬性LEN(D(文= “新增”)) #通過索引獲取實例 ð (文= “新增”)[ 0 ] D(文= “新增”)[ 1 ] ... #迭代器的視圖中 D(文= “添加新”): view.info # ...注意:當您使用選擇喜歡的列表,你必須確保屏幕保持不變,否則你可能會得到UI未找到錯誤。
獲取所選的ui對象狀態及其信息
-
檢查特定ui對象是否存在
D(文= “設置”).exists #是否存在真,否則假 d.exists(文= “設置”)#以上財產的別名。 -
檢索特定ui對象的信息
D(文= “設置”).INFO以下是可能的結果:
{ u'contentDescription': u'', u'checked': False, u'scrollable': False, u'text': u'Settings', u'packageName': u'com.android.launcher', u'selected': False, u'enabled': True, u'bounds': {u'top': 385, u'right': 360, u'bottom': 585, u'left': 200}, u'className': u'android.widget.TextView', u'focused': False, u'focusable': True, u'clickable': True, u'chileCount': 0, u'longClickable': True, u'visibleBounds': {u'top': 385, u'right': 360, u'bottom': 585, u'left': 200}, u'checkable': False } -
設置/清除可編輯字段的文本
D(文= “設置”).clear_text() #清除文字 D(文= “設置”).set_text( “我的文字...... ”) #設置文本
對選中的ui對象執行單擊操作
-
點擊特定的ui對象
#點擊特定的UI對象的中心 D(文= “設置”)。單擊() #點擊具體的UI對象的bottomright角落 D(文= “設置”)).click.bottomright( #請點擊具體的UI對象的左上邊角 D(文= “設置”).click.topleft() #點擊等到新窗口更新 D(文= “設置”).click.wait() -
長時間點擊特定的ui對象
#長按一下特定的UI對象的中心 D(文= “設置”).long_click() #長按具體的UI對象的bottomright角落 D(文= “設置”).long_click.bottomright() #長按具體的UI對象的左上邊角 D(文= “設置”).long_click.topleft()
針對特定ui對象的手勢動作
-
將ui對象拖動到另一個點或ui對象
#注:拖不能設置到Android 4.3的。 #拖拽的UI對象,以點(X,Y) D(文= “設置”).drag.to(X,Y,步驟= 100) #拖拽的UI對象到另一個UI對象(中心), D(文= “設置“).drag.to(文= ”時鍾“,步驟= 50) -
從ui對象的中央滑動到其邊緣
滑動支持4個方向:
leftrighttopbottom
D(文= “設置”).swipe.right() D(文= “設置”).swipe.left(步驟= 10), D(文= “設置”).swipe.up(步驟= 10), D(文字= “設置”).swipe.down() -
兩點手勢從一個點到另一個點
D(文= “設置”).gesture((SX1,SY1),(SX2,SY2))\ 。要((EX1,EY1),(EX2,EY2)) -
在特定ui對象的兩點姿態
支持兩種手勢:
In,從邊到中心Out,從中心到邊緣
#注:捏不能設置到Android 4.3的。 #從邊緣到中心。這里是“在”不“,在” D(文= “設置”).pinch.In(百分比= 100,步= 10) #從中心到邊緣 D(文= “設置”).pinch.Out() -
等待特定ui對象出現或消失
#等到UI對象出現 D(文= “設置”).wait.exists(超時= 3000) #等待,直到UI對象轉眼 D(文= “設置”).wait.gone(超時= 1000) -
對特定的ui對象執行fling(可滾動)
可能的屬性:
horiz要么vertforward或backward或toBeginning或toEnd
#一扔前進(默認)垂直(默認) D(滾動= 真).fling() #一扔前進horizentally D(滾動= 真).fling.horiz.forward() #一扔向后垂直 D(滾動= 真).fling .vert.backward() #一扔到horizentally開始 D(滾動= 真).fling.horiz.toBeginning( max_swipes = 1000) #來結束垂直一扔 D(滾動= 真).fling.toEnd() -
在特定的ui對象上滾動(可滾動)
可能的屬性:
horiz要么vertforward或backward或toBeginning或toEnd或to
#向前滾動(默認)垂直(默認) D(滾動= 真).scroll(步驟= 10) #向前滾動horizentally D(滾動= 真).scroll.horiz.forward(步驟= 100) #向后滾動垂直 D(滾動= 真).scroll.vert.backward() #滾動到horizentally開始 D(滾動= 真).scroll.horiz.toBeginning(步驟= 100, max_swipes = 1000) #滾動到年底垂直 D(滾動= 真)。 scroll.toEnd() #向前滾動,直到垂直特定的UI對象出現 D(滾動= 真).scroll.to(文= “安全性”)
貢獻
- 分叉repo,並克隆到您的計算機。
- 從檢出一個新分支
develop的分支 - 安裝要求:
pip install -r requirements.txt - 進行更改,然后更新測試。不要忘記在“提供者”部分的末尾添加您的姓名
- 通過所有的測試和代碼必須包括:
tox。 - 提交你的修改,並提交拉請求
develop分支。
貢獻者
問題和討論
如果您有任何錯誤報告或煩惱請報告給我們的問題跟蹤GitHub的問題。
如果你有你想討論任何建議,新的功能要求或話題,請提交您的主題ostio。
筆記
- Android的uiautomator適用於Android 4.1及以上版本,所以在使用它之前,請確保你的設備是Android4.1 +。
- 有些方法僅工作在Android 4.2 / 4.3,所以你最好閱讀詳細uiautomator的Java文檔在使用它之前。
- 該模塊采用uiautomator-jsonrpc服務器作為后台程序與設備進行通信。
- 該模塊僅在python2.7 / 3.2 / 3.3 / pypy上測試。
常問問題
-
無法啟動JSONRPC服務器:
raise IOError("RPC server not started!")它可能是由網絡,設備或環境引起的。因此,當您遇到此問題,請按照以下步驟,嘗試手動啟動JSONRPC服務器。
-
從下載jar文件uiautomator jsonrpc服務器。
-
Adb將下載的jar文件推送到
/data/local/tmp/ -
通過命令啟動jsonrpc服務器:
adb shell uiautomator runtest bundle.jar uiautomator-stub.jar -c com.github.uiautomatorstub.Stub -
Adb將本地端口轉發到設備端口:
adb forward tcp:9008 tcp:9008 -
檢查jsonrpc服務器是否正常:
curl -d '{"jsonrpc":"2.0","method":"deviceInfo","id":1}' localhost:9008/jsonrpc/0如果你看到類似的消息
{"jsonrpc":"2.0","id":1,"result":{"currentPackageName":"android","displayHeight":1280,"displayRotation":0,"displaySizeDpX":0,"displaySizeDpY":0,"displayWidth":720,"productName":"falcon","sdkInt":17,"naturalOrientation":true}},則表示服務器已啟動。
如果你可以手動啟動jsonrpc服務器,但你的腳本總是滿足
IOError("RPC server not started!"),請提交問題github上的問題。 -
-
錯誤
httplib.BadStatusLine: ''JsonRPC服務器需要訪問設備上的臨時目錄,但在一些低層設備上,它可能會遇到錯誤,在訪問臨時文件沒有連接SD卡。因此,如果您遇到錯誤,請插入SD卡,然后重試。





