Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 使用Monkeyrunner進行Android自動化的總結

使用Monkeyrunner進行Android自動化的總結

編輯:關於Android編程

使用Android自動化的方式,不僅可以用來對Android APP進行自動化測試,同樣可以用來進行一些其他非常有意思的自動化任務.常用的自動化工具有Monkeyrunner, Robotium, Appium等.Monkeyrunner是Android自帶的自動化測試工具,允許用戶對Android設備的UI界面進行元素提取,執行touch和drag等操作,配合HierarchyViewer等模塊可以非常方便地進行自動化操作.

首先,用戶需要安裝好Android開發環境,同時運行Monkeyrunner腳本需要安裝Jython環境.Jython允許使用Python的語法格式來編寫自動化測試代碼,因此對於Python開發者而言非常有優勢.Python中的一些個別模塊不能直接用於Jython中,這時就需要安裝適用於Jython版本的,具體方法可參考

 

http://stackoverflow.com/questions/3256135/importing-python-modules-in-jython. 如安裝bottle模塊, jython ez_setup.py bottle,然後在使用時導入該模塊即可.

 

 

import sys
sys.path.append('/home/jython2.5.3/Lib/site-packages/bottle-0.12.7-py2.5.egg')
from bottle import Bottle, run, request, response, get, post
使用Monkeyrunner進行Android自動化大概可以分為以下幾種類型的操作:設備及UI界面操作,UI界面元素提取,截圖對比等.

 

1, 設備及UI界面操作

其實,涉及到Android設備的操作,使用開發環境自帶的adb已經足夠了,而Monkeyrunner也是將adb操作封裝了以下而已.常見adb操作如下:

 

	adb install xxx.apk	安裝apk文件
	adb shell am start -an com.xxx.xxx/.MainActivity 啟動APP
	adb shell am force-stop com.xxx.xxx 停止該APP
	adb shell input keyevent KEYCODE_HOME 模擬Android的HOME按鍵
	adb -s emulator-5554 shell input text test_to_input 針對特定的一個模擬器進行操作
	adb shell input tap x y 模擬屏幕touch操作
	adb shell input swipe x1 y1 x2 y2 模擬屏幕滑動操作
	adb devices 查看所有在線的Android設備.

 

詳細的adb命令,可以通過adb -h來查詢.而Monkeyrunner中對設備的操作如下:

 

	from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice
	device = MonkeyRunner.waitForConnection(5,"emulator-5554")
	device.shell("am start -an com.xxx.xxx/.MainActivity")
	device.touch(250, 450, 'DOWN_AND_UP')
	device.drag((1080/2, 1700),(1080/2, 400),0.5,1)
	device.type("text to type")
	device.shell("input text" + "text to input")
	device.press("KEYCODE_HOME")
	# 另外,也可以通過id來進行touch操作,此時可以引入By模塊,可以非常方便通過id尋找對應的元素.
	from com.android.monkeyrunner.easy import EasyMonkeyDevice, By
	easy_device = EasyMonkeyDevice(device)
	easy_device.touch(By.id('id/button1'), easy_device.DOWN_AND_UP)
以上方式其實與adb shell的操作是一致的,只是方便用戶在Jython腳本文件中調用而已.

 

2, UI界面元素提取

Monkeyrunner可以通過HierarchyViewer來對UI界面的元素進行解析,解析的結果與DDMS及Android Studio中的Android Device Monitor保持一致.

首先需要先對UI界面進行解析,然後即可通過元素id和其他的屬性來提取該元素,並對其所有屬性進行解析.

 

	from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
	from com.android.chimpchat.hierarchyviewer import HierarchyViewer
	device = MonkeyRunner.waitForConnection(5,"emulator-5554")
	hViewer = device.getHierarchyViewer() # 對當前UI視圖進行解析
	content = hViewer.findViewById('id/content')  # 通過id查找對應元素
	memberView = content.children[0]
	text = memberView.namedProperties.get('text:mText').value.encode('utf8')
	desc = memberView.namedProperties.get('accessibility:getContentDescription()').value.encode('utf8')
	mleft = memberView.namedProperties.get('layout:mLeft').value.encode('utf8')
	height = memberView.height

 

使用HierarchyViewer來解析界面的層級關系,並根據id來查找特定元素是我們常用的做法.然而,Android APP中,會有很多元素是沒有對應的id的(這一點,可以通過DDMS或者AVD中解析結果看出來),那麼此時,我們如果要精准地找到一個特定元素,就只能通過進一步解析某個元素的children來實現,會比較麻煩,但往往是非常精准的.

需要注意的是,使用HierarchyViewer並通過id來查找元素偶爾會出錯,提示找不到對應的元素.如果遇到實在難以解析出來的元素,可以考慮使用另一個模塊AndroidViewClient進行解析.原理也很類似.甚至有時候,寫法比HierarchyViewer簡潔得多.

 

	vc = ViewClient(device=device, serialno="emulator-5554")
	content = vc.findViewById('id/content')
	memberView = content.children[0]
	text = memberView.getText()
	x = memberView.getX()
	y = memberView.getY()
	height = memberView.getHeight()

 

AndroidViewClient的項目地址是https://github.com/dtmilano/AndroidViewClient.使用時候有個注意事項,我們先將AndroidViewClient寫入環境變量中,然後要先導入AndroidViewClient的模塊,之後再導入Monkeyrunner及相應地其他模塊,否則會出現找不到AndroidViewClient的錯誤.至於為什麼,大家可以自己嘗試一下就明白了.

 

	import sys
	reload(sys)
	sys.setdefaultencoding("utf-8")
	ANDROID_VIEW_CLIENT_HOME = os.environ['ANDROID_VIEW_CLIENT_HOME']
	sys.path.append(ANDROID_VIEW_CLIENT_HOME + '/src')
	from com.dtmilano.android.viewclient import ViewClient, View

	from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
	from com.android.monkeyrunner.easy import EasyMonkeyDevice, By
	from com.android.chimpchat.hierarchyviewer import HierarchyViewer

 

不過以上兩種方式,都有可能出現UI元素解析失敗的情況,原因可能是Android相應工具自身的不完善導致的.因為DDMS和AVD也會經常出現無法解析某個UI界面的情況.

具體的應用場景大家自己斟酌吧,總之,能夠完美獲取到所需元素即可.

3, 截圖對比

這是Monkeyrunner非常有特色的一種方式,常用於通過設備屏幕前後的對比來獲取對執行結果的判斷.

 

	path = "/tmp/images"
	image = device.takeSnapshot() # 截圖
	image.writeToFile(path+"主頁面".decode('utf-8')+now+'.png','png')
	#下面就開始對之前的截圖進行對比了
	#去文件中找到我們要對比的圖片,與該截圖image1進行對比
	result = MonkeyRunner.loadImageFromFile('/tmp/images/result.png')
	#判斷圖片相識度是否是為90%
	if(image.sameAs(result,0.9)):
	    log.write("圖片對比成功……\n")
	else:
	    log.write("主頁面圖片對比失敗……\n")
以上,就是通過Monkeyrunner進行Android自動化的一些基本內容.

 

 

下邊,將大家容易遇到的一些坑記錄下來,造福廣大人民群眾.

Monkeyrunner容易遇到的一些坑:

1, 中文輸入的問題

Monkeyrunner默認只支持Ascii編碼,所以遇到中文,目前是不能通過adb的input和type進行輸入的.那麼可以采用復制到PC剪貼板,然後到Android模擬器裡邊進行粘貼的方式.

但需要注意的是,Android模擬器裡邊的剪貼板的內容是當前PC的焦點從PC桌面環境切換到模擬器界面瞬間時的剪貼板內容.常見情況是,通過Monkeyrunner腳本文件將PC環境中剪貼板內容向Android模擬器粘貼時,往往會出現粘貼不上我們想要的內容.此時,出於調試目的,我們會檢查在當前PC環境的剪貼板中,是否是我們需要的內容.然後將鼠標焦點移入模擬器中,常常發現能夠粘貼上所需的正確內容.,然而,這其實是一個時間差的原因,即PC中的剪貼板內容正確,然後切換到模擬器界面,剪貼板內容是從PC環境帶過來的,當然是正確的了.相反,我們在Monkeyrunner腳本執行後,在剪貼板操作之前即將當前PC的焦點切換到模擬器中,會發現剪貼板內容是不正確的.說得有點亂,大家可以好好琢磨,自己實踐一下.

github上有位同學寫了一個小的工具,可以非常方便地執行Android模擬器中的剪貼板操作,https://github.com/bingwei/inputchineseviaadb.非常好用,大家可以試一試.當然,遇到一些特殊字符,還是需要做一些簡單地轉義等操作的.

2, Monkeyrunner腳本中各個操作的耗時問題

在Monkeyrunner腳本執行過程中,使用HierarchyViewer以及AndroidViewClient進行界面元素解析時,會發現findViewById操作的時間消耗很大.尤其是該UI界面上元素非常多的時候,耗時非常明顯.然而,涉及到界面切換時,我們常常會根據當前界面中是否包含某個id的元素來判斷界面是否切換成功.那麼,在大多數情況下,我們沒有必要根據id來判斷當前界面,通過windowName = device.getHierarchyViewer().focusedWindowName()這種方式,已經足夠我們進行絕大多數的UI界面判斷了,並且在效率上絕對不是一個數量級的提升.

3, 涉及到UI界面之間切換的算法問題

我們常常會遇到,明明就在幾個特定的UI界面之間相互切換,但由於Android自動化環境及工具自身的不穩定性,經常導致屏幕切換延遲,點擊或切換不成功,APP卡住甚至閃退等一些非常苦惱的問題.那麼這就是考驗編碼能力和算法功底的時候.在這一點上,非常感謝教授同學的幫助,贊一個.

我們可以預先定義一個所有常見界面的focusdWindowName及屏幕切換所需的操作行為的結構體,如

 

	SCREEN_SWITCH_ACTION = {
	    'Activity1': {
	        'Activity1': None,
	        'Activity2': ('LEFT_DOWN', 'Activity1'), # 如,從Activity2切換到Activity1需要做LEFT_DOWN的操作.
	        'Activity3': ('LEFT_DOWN', 'Activity1'),
	    },
	    'Activity2': {
	        'Activity1': ('MID_DOWN', 'Activity2'),
	        'Activity2': None,
	        'Activity3': ('MID_DOWN', 'Activity2'),
	    },
	    'Activity3': {
	        'Activity1': ('RIGHT_DOWN', 'Activity3'),
	        'Activity2': ('RIGHT_DOWN', 'Activity3'),	        
	        'Activity3': None,
	    },
	}
如上,該字典中key是目標屏幕,其value值即代表了從當前屏幕切換到目標屏幕所需的操作行為.其中,LEFT_DOWN等可以是簡單地touch一個button,也可以寫出一個負責的根據界面及元素來決定操作行為的負責操作的集合.有了如上的這種結構體,我們只需要寫一個對應的算法,在屏幕切換時從該結構體中解析操作並執行即可.諸如屏幕等待,失敗重試之類的容錯機制,都可以隨意添加了.

 

其實,涉及到這個算法層面的問題,研究和改進的空間實在是太大了.有興趣的同學可以更深入的討論,歡迎指教.

當然,除了Monkeyrunner, Robotium和Appium等工具也都是使用率非常高的,各有優劣吧.
以上這些,就是本次Monkeyrunner自動化的一些總結,寫的比較簡略,歡迎批評指正.

 

 

 



 


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved