IOS 自動化 2-UI Automation-功能測試
1. 常用操作
UI Automation提供了非常多的介面來模擬UI操作,如點選、雙擊、雙指縮放、拖曳等。
單擊。根據輸入的絕對座標點選螢幕。
UIATarget.localTarget().tap({x:100, y:200});
雙擊。根據輸入的絕對座標雙擊螢幕。
UIATarget.localTarget().doubleTap({x:100, y:200});
拉伸。模擬雙指拉伸操作,第一個座標點是起點,第二個座標點是終點,最後一個引數是持續時間,單位為秒。
UIATarget.localTarget().pinchOpenFromToForDuration({x:20, y:200}, {x:300, y:200}, 2);
收縮。模擬雙指收縮操作,第一個座標點是起點,第二個座標點是終點,最後一個引數是持續時間,單位為秒。
UIATarget.localTarget().pinchCloseFromToForDuration({x:20, y:200}, {x:300, y:200}, 2);
拖曳。模擬單指拖曳操作,第一個座標點是起點,第二個座標點是終點,最後一個引數是持續時間,單位為秒。
UIATarget.localTarget().dragFromToForDuration({x:160, y:200}, {x:160, y:400}, 1);
快速滑動。模擬單指快速滑動操作,第一個座標點是起點,第二個座標點是終點,與拖曳不同的是它沒有時間引數,因為這個操作的速度很快。
UIATarget.localTarget().flickFromTo({x:160, y:200}, {x:160, y:400});
除了根據絕對座標進行操作,我們也可以先取得控制元件,然後進行相應的操作。當然,前提是這個控制元件是存在、有效且可見的。根據控制元件模擬操作要特別小心,因為有時候控制元件會被其他控制元件擋住,控制元件還沒被加載出來,或者突然出現了彈框導致無法操作控制元件。
var addButton = UIATarget.localTarget().frontMostApp().navigationBar().buttons()["Add"];
if(addButton.isValid() && addButton.isVisible()){
addButton.tap();
}
如果你還不熟悉UI Automation的介面,那麼錄製功能將給你帶來極大的便利,它會記錄下你每次操作的步驟,生成相應的程式碼。使用方法見UI Automation教程。
2. 輸出測試資訊
我們希望編寫的測試指令碼能包含儘可能多的資訊,以便於發現和分析可能出現的錯誤,而記錄資訊最簡單有效的方式就是編寫Case。下面看一個Case。
var testName = "Module 001 Test";
UIALogger.logStart(testName);
//一些測試程式碼
UIALogger.logPass(testName);
UIALogger是一個用於記錄測試資訊的工具類,我們呼叫它的logStart函式開始一項測試,併為測試項命名。因此,上面這個Case的名稱就是"Module 001 Test"。在執行一段測試程式碼後,我們用logPass或logFail結束一項測試,記錄測試結果(成功或失敗)。
我們還可以用logMessage輸出一些資訊,類似於Java或C裡的print。下面的Case就使用了logMessage,它用起來更自由、方便;並用captureScreenWithName截圖,記錄當時的狀態。除此之外,UIALogger工具類還提供了更多的函式如logError, logWarning等,具體用法參見UIALogger。
var testName = "Module 001 Test"; UIALogger.logStart(testName); //一些測試程式碼 UIALogger.logMessage("Starting Module 001 branch 2, validating input."); //截一張圖,以給定的引數命名 UIATarget.localTarget().captureScreenWithName("SS001-2_AddedIngredient"); //更多測試程式碼 UIALogger.logPass(testName);
3. 處理彈框
UI Automation提供了一個函式介面onAlert來處理彈框,當彈框出現時,將呼叫這個函式。接下來,我們編寫一個非常簡單的彈框處理函式。
UIATarget.onAlert = function onAlert(alert) { var title = alert.name(); UIALogger.logWarning("Alert with title '" + title + "' encountered."); // 返回false,使用預設處理方式 return false; }
這個函式使用logWarning記錄了彈框的名稱,最後返回false,這將意味著點選預設按鈕來關閉彈框。例如,當收到一條簡訊時,這個函式執行的操作是點選“關閉”按鈕,從而關閉彈框。
如果彈框是app內部產生的,並且我們知道它的確切的名字,那麼我們可以執行一些預期的操作,而不僅僅是關閉彈框。下面的程式碼為一個特定的彈框執行了點選“Continue”按鈕的操作,並返回true,當然前提是我們確定“Continue”按鈕是存在的。
UIATarget.onAlert = function onAlert(alert) { var title = alert.name(); UIALogger.logWarning("Alert with title '" + title + "' encountered."); if (title == "The Alert We Expected") { alert.buttons()["Continue"].tap(); return true; //彈框已處理 } //若返回false,則使用預設處理方式 return false; }
4. 指令碼示例
下面以“開源中國”app為例,編寫一個登陸指令碼。點選這裡下載測試應用和指令碼。
var target = UIATarget.localTarget(); //UIATarget是最上層的類,表示真實裝置或模擬器 try{ target.delay(3); //等待3秒,跳過開場動畫 UIALogger.logStart("test 1"); //第1個Case UIALogger.logMessage("開始第一個測試"); var leftButton = target.frontMostApp().navigationBar().leftButton(); //取得導航欄的左側按鈕 leftButton.tap(); //點選 var techCell = target.frontMostApp().mainWindow().tableViews()[0].cells()["技術問答"]; //取得第一個cell if (techCell.isValid() && techCell.isVisible()) { UIALogger.logPass("find 技術問答"); } else { UIALogger.logFail("cannot find 技術問答"); } UIALogger.logStart("test 2"); //第2個Case UIALogger.logMessage("開始第二個測試"); target.frontMostApp().mainWindow().buttons()[0].tap(); target.delay(1); //等待動畫結束 target.frontMostApp().tabBar().buttons()["我"].tap(); target.delay(1); //等待動畫結束 target.frontMostApp().mainWindow().tableViews()[1].cells()["訊息"].tap(); target.delay(1); //等待動畫結束 var loginButton = target.frontMostApp().mainWindow().buttons()["登入"]; if(loginButton.isValid() && loginButton.isVisible()){ //如果登陸按鈕有效且可見,則表示使用者未登入,接下來嘗試登陸 var textField = target.frontMostApp().mainWindow().textFields()[0]; var secureTextField = target.frontMostApp().mainWindow().secureTextFields()[0]; textField.tap(); textField.setValue("username"); //輸入使用者名稱 target.delay(0.5); secureTextField.tap(); secureTextField.setValue("password"); //輸入密碼 target.delay(0.5); loginButton.tap(); target.delay(3); if(loginButton.isValid() && loginButton.isVisible()){ UIALogger.logFail("登陸失敗"); }else{ UIALogger.logPass("登陸成功"); } }else{ UIALogger.logPass("使用者已經登陸"); } }catch(err){ UIALogger.logError(err.toString()); }
5. 學習資料
如果希望學習更多有關JavaScript指令碼編寫和UI Automation框架的內容,請參考下面的資料。