2012-08-10 15:47 by 知平軟件, 15839 閱讀, 5 評論, 收藏, 編輯html
寫在前面ios
研究iOS的自動化測試也有些日子了,剛開始的時候,一直苦於找不到什麼好的資料,只能從Apple的官網查閱相關的API文檔,只惋惜,Apple對開發者來講實在是不怎麼友好,文檔寫得至關的粗略,對於初學者來講有必定的難度。web
原本是打算本身動手寫一篇關於iOS的UI自動化測試的入門級別的介紹性文檔的,但想起來後面在具體解決一些問題的時候,收藏一篇很好的Blog,很全面地介紹瞭如何使用UIAutomation的JavaScript Libraries作iOS程序的自動化測試。若是做者早點看到這篇文章,應該要少走一些彎路,這裏沒有創意性的它他翻譯成中文,但願對大家有一些幫助。xcode
原文地址:http://blog.manbolo.com/2012/04/08/ios-automated-tests-with-uiautomation網絡
翻譯正文:app
快速入門框架
自動化測試代碼能夠「在你的睡着的時候」很好地幫你測試你的應用程序。它可讓你可以快速地跟蹤你程序中的迴歸和性能方面的問題,這樣你就不用擔憂你新增的功能會影響到你以前已經完成開發的程序了。編輯器
隨着iOS4.0的發佈,蘋果公司同時發佈了一個名爲UIAutomation的測試框架,它能夠用來在真實設備和iPhone模擬器上執行自動化測試。但官方關於UIAutomation的文檔至關的有限,在網絡上也沒有太多的資源能夠查找的。本文將向你展現你如何將UIAutomation整合到你的工做流程當中去。ide
做爲基礎知識的準備,你能夠先看一下蘋果公司關於UIAutomation的文檔,另外還有一篇快速入門的介紹蘋果Instruments的文檔也值得看看,固然,若是你有一個免費的Apple開發者帳號的話,你能夠看一下WWDC 2010 - Session 306 – 使用Instruments進行用戶界面自動化測試的幻燈片或者視頻。post
除此以外,包括在Xcode中的OCUnit測試框架也能夠用來爲你的應用程序編寫單元測試。
1. 第一個UIAutomation測試腳本
使用iOS 模擬器
使用iOS設備
2. 處理UIAElement和元素可訪問性(Accessibility)
UIAElement層次結構
模擬用戶操做
3. 經驗分享(讓你的生活變得更簡單)
類庫Tune-up介紹
導入外部腳本
使用強大的命令行
使用錄製交互功能
當遇到問題時,加上「UIATarget.delay(1);」
4. 高級交互
處理非預期和預期的提示框(alerts)
多任務
屏幕方向
5. 總結
有用的連接
一個視頻
1. 你的第一個UIAutomation測試腳本
UIAutomation的功能測試代碼是用Javascript編寫的。UIAutomation和Accessibility有着直接的關係,你將用到經過標籤和值的訪問性來得到UI元素,同時完成相應的交互操做。
下面讓咱們來編寫咱們的第一段測試代碼。
使用iOS模擬器
1. 下載示例應用程序TestAutomation.xcodeproj,並打開它。這個項目是一個很簡單的包含2個tab的tabbar應用程序。
2. 確保選中以下圖所示的「TestAutomation > iPhone 5.0 Simulator」模式(或許你已經切換成5.1了,所以它多是iPhone5.1模擬器)。
3. 啓動Instruments(Product > Profile),或者經過⌘I。
4. 選擇左邊的iOS Simulator,而後再選擇Automation模板,而後點擊「Profile」。
5. Instruments就已經啓動好後,而後直接開始錄製了。這裏先中止錄製,(紅包按鈕或者⌘R)。
6. 在左邊的Scripts窗口,點擊「Add > Create」建立新的腳本。
7. 在腳本編輯器裏,輸入下面的代碼
1
2
3
4
|
var
target = UIATarget.localTarget();
var
app = target.frontMostApp();
var
window = app.mainWindow();
target.logElementTree();
|
8. 從新運行這段腳本⌘R(不須要保存)。腳本跑起來後,你能夠在日誌打完後中止它。
贊一個!咱們就這樣完成了咱們的第一個UIAutomation測試用例。
使用iOS設備
你除了將你的測試用例運行模擬器上,也能夠將它運行在一個真實的設備上。不過,自動化測試用例只能運行在支持多任務的:iPhone 3GS,iPad,iOS > 4.0等設備上。遺憾的是無論iPhone 3G的系統版本是什麼,都不支持。
下面是如何操做:
1. 經過USB接口鏈接上你的iPhone。
2. 選擇 「TestAutomation > iOS Device」模式。
3. 確保Developper profile設置成Release模式(而不是Ad-Hoc Distribution profile)。默認狀況下,profiling是設置成Release模式的(由於沒有必要將profile設置成Debug模式)。
4. 啓動測試 (⌘I)
5. 後面的步驟請參考前面模擬器部分。
2. 處理UIAElement和元素可訪問性(Accessibility)
UIAElement層次結構
Accessibility和UIAutomation有密切的聯繫:若是一個控件的Accessibility是能夠被訪問的,你就能夠設置和讀取它的值,做相關的操做,而當一個控件的Accessibility不可見時,你就沒有辦法經過automation訪問它。
你能夠經過Interface Builder,或者經過在程序裏設置isAccessibilityElement屬性的方式來設置一個控件的Accessibility或者可被自動化。當你設置container view(即:一個視圖包含其它的UIKit元素)的accessibility時,你必須注意。你設置了整個View的accessibility將會「隱藏」它的子視圖的accessibility,例如:在示例項目中,你不能將outlet視圖設置成可訪問的,不然它全部的子控件將都不能夠訪問了。在任什麼時候候,logElementTree都是你忠實的朋友:它將當前界面的全部可被訪問的元素都打印在日誌裏。
每個能夠被訪問的UIKit控件均可以用一個Javascript對象來描述,它就是一個UIAElement。UIAElement有幾個屬性:name, value, elements, parent。你的主窗口包含不少的控件,它們是以UIKit層次的方式定義的,這些UIKit層次結構對應的是UIAElement的層次樹。例如:前面的測試代碼中,經過調用logElementTree,咱們能夠獲得以下面所示的樹結構:
+- UIATarget: name:iPhone Simulator rect:{{0,0},{320,480}}
| +- UIAApplication: name:TestAutomation rect:{{0,20},{320,460}}
| | +- UIAWindow: rect:{{0,0},{320,480}}
| | | +- UIAStaticText: name:First View value:First View rect:{{54,52},{212,43}}
| | | +- UIATextField: name:User Text value:Tap Some Text Here ! rect:{{20,179},{280,31}}
| | | +- UIAStaticText: name:The text is: value:The text is: rect:{{20,231},{112,21}}
| | | +- UIAStaticText: value: rect:{{145,231},{155,21}}
| | | +- UIATabBar: rect:{{0,431},{320,49}}
| | | | +- UIAImage: rect:{{0,431},{320,49}}
| | | | +- UIAButton: name:First value:1 rect:{{2,432},{156,48}}
| | | | +- UIAButton: name:Second rect:{{162,432},{156,48}}
你能夠經過下面的代碼來訪問文本框:
1
2
|
var
textField =
UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];
|
你能夠選擇經過從0開始的索引或者這個元素的名稱來訪問這個元素,例如:你也能夠經過下面的代碼來訪問文本控件。
1
2
|
var
textField =
UIATarget.localTarget().frontMostApp().mainWindow().textFields()[
"User Text"
];
|
後一種方式更加清晰明瞭,應該多使用。你能夠經過Interface Builder設置UIAElement的name屬性,
或者經過編寫代碼的方式:
1
2
|
myTextField.accessibilityEnabled = YES;
myTextField.accessibilityLabel = @
"User Text"
;
|
你如今能夠看到,經過accessibility屬性能夠被UIAutomation用來找到不一樣的控件。這很是的清晰,由於,第一,你只要學習一個測試框架;第二,經過編寫自動化測試代碼,你同時還能夠保證你的程序是能夠被訪問的。所以,每個UIAElement對象的子控件能夠經過下面的方法進行訪問:
buttons(), images(), scrollViews(),textFields(), webViews(), segmentedControls(), sliders(), staticTexts(), switches(), tabBar(),tableViews(), textViews(), toolbar(), toolbars() 等等……
你能夠經過以下代碼在tabbar上訪問第一個tab:
1
2
|
var
tabBar = UIATarget.localTarget().frontMostApp().tabBar();
var
tabButton = tabBar.buttons()[
"First"
];
|
UIAElement結構層次很是的重要,你之後會經常用到它。並且你還要記住,你能夠在隨時經過調用UIAAplication的logElementTree來得到它的結構。
1
|
UIATarget.localTarget().frontMostApp().logElementTree();
|
在模擬器上,你還能夠激活Accessibility 的檢測器。啓動模擬器,找到「Settings > General > Accessibility > Accessibility Inspector」,而後將它設爲「打開」狀態。
這個彩色的小框框就是Accessibility 檢測器了。當它收起來的時候,Accessibility就被關閉了,當它展開的時候,Accessibility就是打開的。你只要點擊上面的箭頭按鈕就能夠激活或者屏蔽Accessibility。如今,打開咱們的示例程序,激活檢測器。
而後,點擊文本框,檢查UIAElement的name和value屬性(其實就是accessibilityLabel和accessibilityValue對應的NSObject類型的值)。這個檢測器能夠幫助你調試和編寫你的測試代碼。
模擬用戶操做
讓咱們更進一步,模擬一些用戶的交互操做。你能夠簡單地調用按鈕的tap()來做一個點擊操做:
1
2
3
4
5
|
var
tabBar = UIATarget.localTarget().frontMostApp().tabBar();
var
tabButton = tabBar.buttons()[
"First"
];
// Tap the tab bar !
tabButton.tap();
|
你還能夠調用UIAButtons的doubleTap(), twoFingerTap()。若是你不想操做具體的某個元素,你也能夠直接根據屏幕上指定的座標點進行操做,你能夠這麼用:
點擊:
1
2
3
|
UIATarget.localTarget().tap({x:100, y:200});
UIATarget.localTarget().doubleTap({x:100, y:200});
UIATarget.localTarget().twoFingerTap({x:100, y:200});
|
縮放:
1
2
|
UIATarget.localTarget().pinchOpenFromToForDuration({x:20, y:200},{x:300, y:200},2);
UIATarget.localTarget().pinchCloseFromToForDuration({x:20, y:200}, {x:300, y:200},2);
|
拖拽與划動:
1
2
|
UIATarget.localTarget().dragFromToForDuration({x:160, y:200},{x:160,y:400},1);
UIATarget.localTarget().flickFromTo({x:160, y:200},{x:160, y:400});
|
注意,當你指定操做的時間間隔的時候,它是有特定的範圍的,即:拖拽操做的時間間隔必須大於或者等於0.5秒,小於60秒。
如今,讓咱們來練習一下:
中止Instruments (⌘R)
在Scripts窗口裏, 移除當前的腳本
點擊「Add > Import」而後選擇TestAutomation/TestUI/Test-1.js(將下面的代碼保存到這個路徑)
點擊錄製按鈕 (⌘R) 而後看看將會發生什麼…
下面是Test-1.js代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
var
testName =
"Test 1"
;
var
target = UIATarget.localTarget();
var
app = target.frontMostApp();
var
window = app.mainWindow();
UIALogger.logStart( testName );
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();
if
(textValue === recipeName){
UIALogger.logPass( testName );
}
else
{
UIALogger.logFail( testName );
}
|
這段腳本先啓動待測程序,而後,若是第一個tab沒有被選的話就切換到第一個tab,並將上面的文本框的值設成「Unusually Long Name for a Recipe」,接着收起虛擬鍵盤。這裏有一些新的方法值得注意的:UIATarget的delay(Number timeInterval) 方法容許你在兩個操做之間作一些等待,UIALogger的logMessage( String message) 方法用來將你想打印的信息輸出到日誌上去,UIALogger的logPass(String message)方法指明你的測試腳本已經成功的完成測試了。
你還知道了如何訪問鍵盤上的按鈕,而後做點擊操做:
1
|
app.keyboard().buttons()[
"return"
].tap();
|
因爲時間有限且原文太長,先只能翻譯到這裏,我會盡快的將剩下的部分翻譯補上。另外,時間倉促,若有翻譯得不許確的地方,也敬請擔待。謝謝。
本文由知平軟件的Dawson Liu翻譯,轉載請註明出處。
知平軟件致力於移動平臺自動化測試技術的研究,咱們但願經過向社區貢獻知識和開源項目,來促進行業和自身的發展。