安卓自動化測試,賀曉聰之uiautomator設備和選擇器~Python詳解


1、設備對象

引入uiautomator,獲取設備對象<所謂設備對象可理解為:Android模擬器或者真機>

語法:from uiautomator import device as d

d 即為設備對象

1.1、獲取設備信息

語法: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
}

返回值解釋如下:

displayRotation  0 代表豎屏 1 代表橫屏

currentPackageName  當前的Activity的Package名字

productName  當前設備名稱

displayWidth  當前設備屏幕寬度  當 displayRotation 取值為 1 時,也就是說當前是橫屏狀態時,displayWidth 取值會和 displayHeight 互換

displayHeight 當前設備屏幕高度  當 displayRotation 取值為 1 時,也就是說當前是橫屏狀態時,displayHeight 取值會和 displayWidth 互換

sdkInt 當前SDK版本

naturalOrientation 當 displayRotation 取值為 1 時,也就是說當前是橫屏狀態時,取值為False,為豎屏狀態時,取值為:True

1.2、點亮或熄滅屏幕(Turn on/off screen)

# Turn on screen
d.screen.on()
# Turn off screen
d.screen.off()
# wakeup the device
d.wakeup()
# sleep the device, same as turning off the screen.
d.sleep()

檢查屏幕狀態,關閉OR點亮?

if d.screen == "on":  # of d.screen != "off"
    # do something in case of screen on
    pass
if d.screen == "off":  # of d.screen != "on"
    # do something in case of screen off
    pass

1.3、系統常用按鍵

# press home key
d.press.home()
# press back key
d.press.back()
# the normal way to press back key
d.press("back")
# press keycode 0x07('0') with META ALT(0x02) on
d.press(0x07, 0x02)

下面的這些按鍵也是被支持的,如下:

Next keys are currently supported:

  • home                   #手機Home鍵
  • back                   #手機返回鍵
  • left                   #對應鍵盤上的向右鍵<-
  • right                  #對應鍵盤上的向右鍵->
  • up                    #對應鍵盤上的向上鍵
  • down                   #對應鍵盤上的向下鍵
  • center                  #選中?
  • menu                   #菜單
  • search                  #查找?
  • enter                  #對應鍵盤上的Enter鍵
  • delete(or del)                          #對應鍵盤上的DEL鍵 用於刪除
  • recent(recent apps)                  #任務切換
  • volume_up                #聲音向上調整
  • volume_down               #聲音向下調整
  • volume_mute               #靜音按鍵
  • camera                  #拍照
  • power                   #電源鍵

1.4、與設備交互(單擊、長按、滑動(手勢密碼)、拖拽)

單擊屏幕坐標點

# click (x, y) on screen
d.click(x, y)

長按屏幕坐標點

# long click (x, y) on screen
d.long_click(x, y)

在屏幕上滑動

# swipe from (sx, sy) to (ex, ey)
d.swipe(sx, sy, ex, ey)
# swipe from (sx, sy) to (ex, ey) with 10 steps
d.swipe(sx, sy, ex, ey, steps=10)

在屏幕上拖拽

# drag from (sx, sy) to (ex, ey)
d.drag(sx, sy, ex, ey)
# drag from (sx, sy) to (ex, ey) with 10 steps
d.drag(sx, sy, ex, ey, steps=10)

1.5、屏幕操作及屏幕方向獲取與控制<上述:displayRotation  0 代表豎屏 1 代表橫屏>,豎屏分為 natural(自然的,正常的豎屏) 和 upsidedown(倒過來的豎屏),橫屏分為向左和向右兩個方向,分別為:left 和 right 

設備屬性:orientation 可能取得值為:

  • natural or n
  • left or l
  • right or r
  • upsidedown or u (can not be set)

說明:在手機設備上,倒過來的屏幕很少見,因此:d.orientation 取值 upsidedown 的可能性幾乎沒有

# retrieve orientation, it may be "natural" or "left" or "right" or "upsidedown" 獲取設備屏幕方向如下:
orientation = d.orientation
# set orientation and freeze rotation.
# notes: "upsidedown" can not be set until Android 4.3.                          設置設備屏幕方向如下:
d.orientation = "l" # or "left"
d.orientation = "r" # or "right"
d.orientation = "n" # or "natural"

鎖屏/解除鎖屏

# freeze rotation
d.freeze_rotation() #鎖屏
# un-freeze rotation
d.freeze_rotation(False) #解鎖

截屏操作

# take screenshot and save to local file "home.png", can not work until Android 4.2.
d.screenshot("home.png")

打開通知或快速設置

# open notification, can not work until Android 4.3.
d.open.notification()
# open quick settings, can not work until Android 4.3.
d.open.quick_settings()

注意:(如果notification已經打開了,調用d.open.quick_settings()不會打開快速設置)

等待空閑或窗口更新(Wait for idle or window update)

# wait for current window to idle
d.wait.idle()
# wait until window update event occurs
d.wait.update()

2、uiautomator 選擇器

選擇器是在當前窗口中標識特定的UI對象。可理解為:UiObject對象

目前,在uiautomator中支持以下屬性選擇器:

text, textContains, textMatches, textStartsWith
className, classNameMatches
description, descriptionContains, descriptionMatches, descriptionStartsWith
checkable, checked, clickable, longClickable
scrollable, enabled,focusable, focused, selected
packageName, packageNameMatches
resourceId, resourceIdMatches
index, instance

下面依次進行解讀:

2.1、text選擇器(支持在uiautomator中Text屬性不為空的元素)

例如:

具體用法如下:

d(text="Maps").click()
#當然也可以多個屬性在一塊使用
d(text="Maps",className="android.widget.TextView").click()
#或者
d(text="Maps",className="android.widget.TextView",packageName="com.google.android.apps.nexuslauncher").click()

總之:要盡可能的使用選擇器唯一確定一個被選擇對象(UiObject)

除了可以進行選擇UiObject對象以外,我們亦可以使用選擇器設置某些元素的值,如下:

#輸入短信目標手機號
d(text="To").set_text("10086")
#如果本窗口中有多個text為To的元素,我們也可以使用多屬性選擇
d(text="To",packageName="com.google.android.apps.messaging").set_text("10086").set_text("10086")

textContains,textMaches,textStartsWith 分別代表:包含,正則表達式,以XXX開頭等

例如:

d(text="Name").set_text("John")

d(textContains="ame").set_text("John")

d(textStartsWith="Nam").set_text("John")

2.2、className,classNameMatches 類選擇器 及 descriptiondescriptionContainsdescriptionMatchesdescriptionStartsWith 描述選擇器 及 packageNamepackageNameMatches 包選擇器 及 resourceIdresourceIdMatches ResId選擇器用法和text選擇器類似,都可以多屬性選擇器結合在一起使用。

示例代碼如下:

# To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView'
d(text='Clock', className='android.widget.TextView')
d(description="add new contact").click()
d(descriptionContains="new contact").click()
d(descriptionStartsWith="add new").click()
#resourceid選擇器
d(resourceId="com.android.contacts:id/menu_save").click()
#text選擇器
d(textStartsWith="Nam").set_text("John")
#描述選擇器
d(descriptionContains="new contact").click()
#多屬性結合
d(text="Name",className="android.widget.EditText").set_text("John")
#index選擇器和child選擇器
d(resourceId="com.android.settings:id/list").child(className="android.widget.LinearLayout", index=2).child(resourceId="android:id/widget_frame").child(resourceId="android:id/switch_widget").click()

在此,說明下child、sibling選擇器和index選擇器及instance選擇器(嚴格講instance不是選擇器,僅僅只是在輸出多個結果的情況下,可以通過索引(下標)進行選擇)

首先說明child選擇器,sibling選擇器:分別可理解為:子選擇器(可嵌套),兄弟姐妹選擇器

如上圖右邊部分,從上到下層次分為四層,最后一層的兩個元素可理解為兄弟姐妹,在此,我們如果要選擇最下面的那個元素就可以用到child選擇器及sibling選擇器,當然,本人不建議使用孩子,兄妹選擇器,如果能用其他方法實現,建議用其他方法:

在此,我寫的方法如下:<沒有具體驗證,僅僅只是演示>

#孩子選擇器及兄弟姐妹選擇器的用法:child/sibling
d(resourceId="id/pager").child(className="android.widget.FrameLayout").child(resourceId="id/empty_view").child(resourceId="id/empty_image_hint").sibling(packageName="com.google.android.apps.messaging")

2.3、index選擇器及instance,比較容易混淆的兩個,一個是選擇器,一個代表索引,如下:

index選擇器對應uiautomator的index屬性,如下:

其用法和text選擇器大同小異,不過在此需要指出的是,有些窗體中index取值會發生改變,因此,能不用index選擇器的,盡可能不用!

#index選擇器
d(className="android.widget.LinearLayout", index=2).click()

instance 的用法:當你的選擇器返回的結果不是指向唯一元素時(兩個或者多個),你可以通過instance進行選擇。

賀曉聰原文:

Multiple instances

Sometimes the screen may contain multiple views with the same e.g. text, then you will have to use "instance" properties in selector like below:

d(text="Add new", instance=0)  # which means the first instance with text "Add new"

However, uiautomator provides list like methods to use it.

# get the count of views with text "Add new" on current screen
d(text="Add new").count

# same as count property
len(d(text="Add new"))

# get the instance via index
d(text="Add new")[0]
d(text="Add new")[1]
...

# iterator
for view in d(text="Add new"):
    view.info  # ...

2.4、獲取選定的UI對象狀態及其信息(Get the selected ui object status and its information)

檢測特定的UI對象是否存在(Check if the specific ui object exists)

兩種寫法,如下:

d(text="Settings").exists # True if exists, else False
d.exists(text="Settings") # alias of above property.

檢索特定UI對象的信息(Retrieve the info of the specific ui object)

d(text="Settings").info

(結果為列表List),如下:

{ 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(text="Settings").clear_text()  # clear the text
d(text="Settings").set_text("My text...")  # set the text

執行單擊特定的UI對象

# click on the center of the specific ui object
d(text="Settings").click()
# click on the bottomright corner of the specific ui object  單擊右下方
d(text="Settings").click.bottomright()
# click on the topleft corner of the specific ui object   單擊左上方
d(text="Settings").click.topleft()
# click and wait until the new window update  單擊並等待窗體響應
d(text="Settings").click.wait()

長時間點擊特定的ui對象,雙擊?

# long click on the center of the specific ui object
d(text="Settings").long_click()
# long click on the bottomright corner of the specific ui object 右下角
d(text="Settings").long_click.bottomright()
# long click on the topleft corner of the specific ui object 左上角
d(text="Settings").long_click.topleft()

將UI對象拖動到另一點

# notes : drag can not be set until Android 4.3.
# drag the ui object to point (x, y)
d(text="Settings").drag.to(x, y, steps=100)
# drag the ui object to another ui object(center)  拖拽到text='Clock'的對象位置上
d(text="Settings").drag.to(text="Clock", steps=50)

滑動UI對象

滑動分為四個方向:left ,right,top ,bottom 即:左滑動 右滑動 上滑動 及向下滑動

d(text="Settings").swipe.right()
d(text="Settings").swipe.left(steps=10)
d(text="Settings").swipe.up(steps=10)
d(text="Settings").swipe.down()

Two point gesture from one point to another

d(text="Settings").gesture((sx1, sy1), (sx2, sy2)) .to((ex1, ey1), (ex2, ey2))

Two point gesture on the specific ui object

Supports two gestures:

  • In, from edge to center
  • Out, from center to edge
# notes : pinch can not be set until Android 4.3.
# from edge to center. here is "In" not "in"
d(text="Settings").pinch.In(percent=100, steps=10)
# from center to edge
d(text="Settings").pinch.Out()

3 point gesture

d().gestureM((sx1, sy1), (sx2, sy2),(sx3, sy3)) \
                  .to((ex1, ey1), (ex2, ey2),(ex3,ey3))
d().gestureM((100,200),(300,200),(600,200),(100,600),(300,600),(600,900))

等到特定的UI對象出現或消失

# wait until the ui object appears
d(text="Settings").wait.exists(timeout=3000)
# wait until the ui object gone
d(text="Settings").wait.gone(timeout=1000)

在具體的UI對象執行甩(滾動)Perform scroll on the specific ui object(scrollable)

Possible properties:

  • horiz or vert
  • forward or backward or toBeginning or toEnd
# fling forward(default) vertically(default) 
d(scrollable=True).fling()
# fling forward horizentally
d(scrollable=True).fling.horiz.forward()
# fling backward vertically
d(scrollable=True).fling.vert.backward()
# fling to beginning horizentally
d(scrollable=True).fling.horiz.toBeginning(max_swipes=1000)
# fling to end vertically
d(scrollable=True).fling.toEnd()

Perform scroll on the specific ui object(scrollable)-在具體的UI對象執行甩(滾動)

Possible properties:

  • horiz or vert
  • forward or backward or toBeginning or toEnd, or to
# scroll forward(default) vertically(default)
d(scrollable=True).scroll(steps=10)
# scroll forward horizentally
d(scrollable=True).scroll.horiz.forward(steps=100)
# scroll backward vertically
d(scrollable=True).scroll.vert.backward()
# scroll to beginning horizentally
d(scrollable=True).scroll.horiz.toBeginning(steps=100, max_swipes=1000)
# scroll to end vertically
d(scrollable=True).scroll.toEnd()
# scroll forward vertically until specific ui object appears
d(scrollable=True).scroll.to(text="Security")

感謝賀曉聰的無私奉獻,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM