如何使用UIAutomation進行iOS 自動化測試(Part II)


接着上一篇《如何使用UIAutomation進行iOS 自動化測試(Part I)

 

3. 經驗分享(讓你生活變得更簡單)

類庫Tune-up介紹

現在你應該基本上知道如何編寫測試代碼了。但你慢慢地會發現,你會經常寫到一些重復的,冗余的,黏糊糊的代碼,像下面一樣:

var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();

這也是為什么我們會用到一個小的Javascript類庫來簡化我們寫的UIAutomation測試的原因。你可以去 https://github.com/alexvollmer/tuneup_js獲取這個類庫,然后將它復制到你的測試目錄下面。現在讓我們使用Tune-Up類庫來重新編寫我們的Test1.js:

#import "tuneup/tuneup.js"

test("Test 1", function(target, app) {
	var window = app.mainWindow();
	app.logElementTree();

	//-- select the elements
	UIALogger.logMessage( "Select the first tab" );
	var tabBar = app.tabBar();
	var selectedTabName = tabBar.selectedButton().name();

	if (selectedTabName != "First") {
		tabBar.buttons()["First"].tap();
	}

	//-- tap on the text fiels
	UIALogger.logMessage( "Tap on the text field now" );
	var recipeName = "Unusually Long Name for a Recipe";
	window.textFields()[0].setValue(recipeName);
	target.delay( 2 );

	//-- tap on the text fiels
	UIALogger.logMessage( "Dismiss the keyboard" );
	app.logElementTree();
	app.keyboard().buttons()["return"].tap();
	var textValue = window.staticTexts()["RecipeName"].value();
	assertEquals(recipeName, textValue);
});

Tune-Up可以避免你編寫重復的代碼,同時還給你提供了各種好用的斷言方法:

ssertTrue(expression, message),
assertMatch(regExp, expression, message),
assertEquals(expected, received, message),
assertFalse(expression, message),
assertNull(thingie, message),
assertNotNull(thingie, message),
assertNull(thingie, message),
assertNotNull(thingie, message)

等等

你也可以很容易的擴展這個類庫:例如,你可以通過將方法加入到uiautomation-ext.js:里面來為UIATarget類加一個logDevice方法:

extend(UIATarget.prototype, {
		logDevice: function(){
		UIALogger.logMessage("Dump Device:");
		UIALogger.logMessage(" model: " + UIATarget.localTarget().model());
		UIALogger.logMessage(" rect: " + JSON.stringify(UIATarget.localTarget().rect()));
		UIALogger.logMessage(" name: "+ UIATarget.localTarget().name());
		UIALogger.logMessage(" systemName: "+ UIATarget.localTarget().systemName());
		UIALogger.logMessage(" systemVersion: "+ UIATarget.localTarget().systemVersion());
	}
});

然后當你調用target.logDevice()就可以看到:

Dump Device:
model: iPhone Simulator
rect: {"origin":{"x":0,"y":0},"size":{"width":320,"height":480}}
name: iPhone Simulator

導入外部腳本

你也可以看到如何在一個腳本文件里引用另一個腳本,即通過#import指令。因此,你可以創建多個測試文件,然后將它們通過導入到單個文件的方式來鏈接並調用它們:

#import "Test1.js"
#import "Test2.js"
#import "Test3.js"
#import "Test4.js"
#import "Test5.js"

使用強大的命令行

如果你想讓你的測試代碼自動的運行起來,你還可以通過命令行來啟動測試。其實,我比較推薦這種方式,而不是使用Instruments的圖形界面程序。因為,Instruments的圖形界面程序比較慢,而且即使你的測試代碼跑完了它也還是會一直運行着。而通過命令行來啟動和運行測試代碼更快,它會在跑完測試后自動的停止。

為了可以在命令行終端運行你的腳本,你需要知道你設備的UDID和類型:

instruments -w your_ios_udid -t 
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Instruments/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate 
name_of_your_app -e UIASCRIPT absolute_path_to_the_test_file 

例如,使用我自己的機子,就這么寫的:

instruments -w a2de620d4fc33e91f1f2f8a8cb0841d2xxxxxxxx -t 
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Instruments/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate 
TestAutomation -e UIASCRIPT 
/Users/jc/Documents/Dev/TestAutomation/TestAutomation/TestUI/Test-2.js 

clip_image002

如果你使用的Xcode版本低於4.3的話,你需要這樣寫:

instruments -w your_ios_device_udid -t /Developer/Platforms/iPhoneOS.platform/Developer/Library/Instruments/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate TestAutomation -e UIASCRIPT /Users/jc/Documents/Dev/TestAutomation/TestAutomation/TestUI/Test-2.js 

一個小提示,不要忘了關閉你設備的密碼驗證,否則你會看到這樣的日志信息的:remote exception encountered : ’device locked : Failed to launch process with bundle identifier ’com.manbolo.testautomation’. 的確,因為UIAutomation根本不知道你的密碼啊。

命令行終端同樣可以在模擬器上使用,但你需要知道待測應用程序在文件系統中的絕對路徑。模擬器將目錄~/Library/Application Support/iPhone Simulator/5.1/ “模擬”成了設備的文件系統。在這個目錄下,你可以找到一個包含裝在模擬器上的所有應用程序的沙盒的Applications文件夾。定位到TestAutomation程序的目錄,然后:

instruments -t /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Instruments/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate "/Users/jc/Library/Application Support/iPhone Simulator/5.1/Applications/C28DDC1B-810E-43BD-A0E7-C16A680D8E15/TestAutomation.app" -e UIASCRIPT /Users/jc/Documents/Dev/TestAutomation/TestAutomation/TestUI/Test-2.js

最后,如果你沒有指定日志輸入到哪里的話,你的測試結果會被放到你命令行當前指定(工作)的目錄下。你可以通過加入 -e UIARESULTSPATH results_path 參數來指定日志輸入目錄。

我沒有成功的將多個測試腳本並行着在命令行中運行起來。但是你可以將你的測試腳本串連進來,有一整晚去跑它,這樣就真正的實現了“在你睡着的時候”,就完成了對應用程序的測試。

使用錄制交互功能

除了手動的編寫腳本,你還可以直接在設備上或者模擬器上錄制腳本,然后替換掉原來的。下面是步驟:

1. 啟動Instruments (⌘I)

2. 創建一個新的腳本

3. 選擇腳本編輯器

clip_image003

4. 在腳本編輯器的底端,你是否看到了一個紅色的按鈕?點擊它!

clip_image004

5. 現在,你可以操作你的應用程序;你將看到錄制的交互操作出現在腳本窗口(甚至旋轉事件)。點擊方形按鈕來停止錄制。

clip_image005

當遇到問題時,加上“UIATarget.delay(1);

當你在編寫腳本的時候,你總是在與時間,動畫打交道。UIAutomation有很多方式去獲取控件元素,然后等待它們變為可用狀態,即使有時候它們還沒有顯示出來,但根據這篇文檔里提到的,最好的建議是:

當遇到問題時,加上UIATarget.delay(1);!

4. 高級交互

處理非預期和預期的提示框(alerts

在寫自動化測試過程中,處理提示框是很難的一件事情:你已經很認真的寫好了你的測試用例,然后在你准備睡覺之前將它跑起來,然后,到第二天早上,你發現你的測試用例被一個未知消息提示框給毀了。然而,UIAutomation幫助你處理了這種情況。

通過下面代碼來實現:

UIATarget.onAlert = function onAlert(alert){
	var title = alert.name();
	UIALogger.logWarning("Alert with title ’" + title + "’ encountered!");
	return false; // use default handler
}

它返回一個false,UIAutomation會自動的幫你銷毀UIAlertView窗口,因此提示框就不會再影響你的測試了。你的測試腳本就永遠不會有提示框彈出了。但是提示框可能是你應用程序的一部分,涉及到你測試的流程,所以,有時候,你不希望它被自動的處理掉。這時,你可以根據提示框的標題來決定,點擊某個按鈕,然后返回true。通過返回true,你向UIAutomation指定這個提示框必須作為測試的一部分來考慮。

例如,如果你想當提示框的標題為“Add Something”時,點擊“Add”按鈕,你可以這么寫:

UIATarget.onAlert = function onAlert(alert) {
	var title = alert.name();
	UIALogger.logWarning("Alert with title ’" + title + "’ encountered!");
	if (title == "Add Something") {
		alert.buttons()["Add"].tap();
		return true; // bypass default handler
	}
	return false; // use default handler
}

容易吧?

多任務

測試你的應用程序的多任務是非常容易的事:假設你想測試每次啟動一個瘋狂的后台進程,將程序放到后台執行,並進入(void)applicationWillEnterForeground:(UIApplication *)application選擇器代碼段,你可以通過下面的代碼來將它推至后台,然后等待10秒后自動返回活動狀態。.

UIATarget.localTarget().deactivateAppForDuration(10);

deactivateAppForDuration(duration) 方法會暫停測試腳本的執行,模擬用戶點擊Home按鈕,(即將程序放到后台),等待,然后為你重新激活程序和測試腳本,就這么一行代碼而已!

屏幕方向

最后,你可以模擬你的iPhone的旋轉方向。也是很直觀很簡單:

var target = UIATarget.localTarget();
var app = target.frontMostApp();
// set landscape left
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation());
// portrait
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation()); 

 

5. 總結

有用的鏈接

這篇文章有點兒長,但我希望你們能見識到UIAutomation是很強大的,且你的應用程序是可以得到質量的保障的。網上沒有太多的UIAutomation的資料,但我還是列出了很多鏈接,也許能幫到你。

當然還有:

你需要一個免費的開發者賬號去訪問這些資源。

一個視頻

在介紹完UIAutomation之后,我不反對向你們展示我們是如何使用在Meon中使用 UIAutomation的一段小視頻。我們使用了各種測試,在這個視頻中,我們測試了玩家可以從0級玩到120級。幫幫我,我的iPhone還活着呢!

http://player.vimeo.com/video/39888743?title=0&byline=0&portrait=0

jc

 

本文由知平軟件的Dawson Liu翻譯,轉載請注明出處。

知平軟件致力於移動平台自動化測試技術的研究,我們希望通過向社區貢獻知識和開源項目,來促進行業和自身的發展。


免責聲明!

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



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