qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

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

           寫在前面

            研究iOS的自動化測試也有些日子了,剛開始的時候,一直苦于找不到什么好的資料,只能從Apple的官網(wǎng)查閱相關(guān)的API文檔,只可惜,Apple對開發(fā)者來說實在是不怎么友好,文檔寫得相當(dāng)?shù)拇致裕瑢τ诔鯇W(xué)者來說有一定的難度。

            本來是打算自己動手寫一篇關(guān)于iOS的UI自動化測試的入門級別的介紹性文檔的,但想起來后面在具體解決一些問題的時候,收藏一篇很好的Blog,很全面地介紹了如何使用UIAutomation的JavaScript Libraries做iOS程序的自動化測試。如果作者早點看到這篇文章,應(yīng)該要少走一些彎路,這里沒有創(chuàng)意性的把他翻譯成中文,希望對你們有一些幫助。

            快速入門

            自動化測試代碼可以“在你的睡著的時候”很好地幫你測試你的應(yīng)用程序。它可以讓你能夠快速地跟蹤你程序中的回歸和性能方面的問題,這樣你就不用擔(dān)心你新增的功能會影響到你之前已經(jīng)完成開發(fā)的程序了。

            隨著iOS4.0的發(fā)布,蘋果公司同時發(fā)布了一個名為UIAutomation的測試框架,它可以用來在真實設(shè)備和iPhone模擬器上執(zhí)行自動化測試。但官方關(guān)于UIAutomation的文檔相當(dāng)?shù)挠邢蓿诰W(wǎng)絡(luò)上也沒有太多的資源可以查找的。本文將向你展示你如何將UIAutomation整合到你的工作流程當(dāng)中去。

            作為基礎(chǔ)知識的準(zhǔn)備,你可以先看一下蘋果公司關(guān)于UIAutomation的文檔,另外還有一篇快速入門的介紹蘋果Instruments的文檔也值得看看,當(dāng)然,如果你有一個免費的Apple開發(fā)者賬號的話,你可以看一下WWDC 2010 - Session 306 – 使用Instruments進行用戶界面自動化測試的幻燈片或者視頻。

            除此之外,包括在Xcode中的OCUnit測試框架也可以用來為你的應(yīng)用程序編寫單元測試

            1、第一個UIAutomation測試腳本

            ● 使用iOS 模擬器

            ● 使用iOS設(shè)備

            2、處理UIAElement和元素可訪問性(Accessibility)

            ● UIAElement層次結(jié)構(gòu)

            ● 模擬用戶操作

            3、經(jīng)驗分享(讓你的生活變得更簡單)

            ● 類庫Tune-up介紹

            ● 導(dǎo)入外部腳本

            ● 使用強大的命令行

            ● 使用錄制交互功能

            ● 當(dāng)遇到問題時,加上“UIATarget.delay(1);”

            4、高級交互

            ● 處理非預(yù)期和預(yù)期的提示框(alerts)

            ● 多任務(wù)

            ● 屏幕方向

            5、總結(jié)

            ● 有用的鏈接

            ● 一個視頻

            1、你的第一個UIAutomation測試腳本

            UIAutomation的功能測試代碼是用Javascript編寫的。UIAutomation和Accessibility有著直接的關(guān)系,你將用到通過標(biāo)簽和值的訪問性來獲得UI元素,同時完成相應(yīng)的交互操作。

            下面讓我們來編寫我們的第一段測試代碼。

            使用iOS模擬器

            1)下載示例應(yīng)用程序TestAutomation.xcodeproj,并打開它。這個項目是一個很簡單的包含2個tab的tabbar應(yīng)用程序。

            2)確保選中如下圖所示的“TestAutomation > iPhone 5.0 Simulator”模式(或許你已經(jīng)切換成5.1了,因此它可能是iPhone5.1模擬器)。

            3)啟動Instruments(Product > Profile),或者通過⌘I。

            4)選擇左邊的iOS Simulator,然后再選擇Automation模板,然后點擊“Profile”。



           5)Instruments就已經(jīng)啟動好后,然后直接開始錄制了。這里先停止錄制,(紅包按鈕或者⌘R)。

            6)在左邊的Scripts窗口,點擊“Add > Create”創(chuàng)建新的腳本。

            7)在腳本編輯器里,輸入下面的代碼

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

            8)重新運行這段腳本⌘R(不需要保存)。腳本跑起來后,你可以在日志打完后停止它。

            贊一個!我們就這樣完成了我們的第一個UIAutomation測試用例。

           使用iOS設(shè)備

            你除了將你的測試用例運行模擬器上,也可以將它運行在一個真實的設(shè)備上。不過,自動化測試用例只能運行在支持多任務(wù)的:iPhone 3GS,iPad,iOS > 4.0等設(shè)備上。遺憾的是不管iPhone 3G的系統(tǒng)版本是什么,都不支持。

            下面是如何操作:

            1)通過USB接口連接上你的iPhone。

            2)選擇 “TestAutomation > iOS Device”模式。

            3)確保Developper profile設(shè)置成Release模式(而不是Ad-Hoc Distribution profile)。默認情況下,profiling是設(shè)置成Release模式的(因為沒有必要將profile設(shè)置成Debug模式)。

            4)啟動測試 (?I)

            5)后面的步驟請參考前面模擬器部分。

            2、處理UIAElement和元素可訪問性(Accessibility)

            UIAElement層次結(jié)構(gòu)

            Accessibility和UIAutomation有密切的聯(lián)系:如果一個控件的Accessibility是可以被訪問的,你就可以設(shè)置和讀取它的值,作相關(guān)的操作,而當(dāng)一個控件的Accessibility不可見時,你就沒有辦法通過automation訪問它。

            你可以通過Interface Builder,或者通過在程序里設(shè)置isAccessibilityElement屬性的方式來設(shè)置一個控件的Accessibility或者可被自動化。當(dāng)你設(shè)置container view(即:一個視圖包含其它的UIKit元素)的accessibility時,你必須注意。你設(shè)置了整個View的accessibility將會“隱藏”它的子視圖的accessibility,例如:在示例項目中,你不能將outlet視圖設(shè)置成可訪問的,否則它所有的子控件將都不可以訪問了。在任何時候,logElementTree都是你忠實的朋友:它將當(dāng)前界面的所有可被訪問的元素都打印在日志里。

            每一個可以被訪問的UIKit控件都可以用一個Javascript對象來描述,它就是一個UIAElement。UIAElement有幾個屬性:name, value, elements, parent。你的主窗口包含很多的控件,它們是以UIKit層次的方式定義的,這些UIKit層次結(jié)構(gòu)對應(yīng)的是UIAElement的層次樹。例如:前面的測試代碼中,通過調(diào)用logElementTree,我們可以得到如下面所示的樹結(jié)構(gòu):

            +- 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}}



          你可以通過下面的代碼來訪問文本框:

          var textField =  
          UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];

            你可以選擇通過從0開始的索引或者這個元素的名稱來訪問這個元素,例如:你也可以通過下面的代碼來訪問文本控件。

          var textField =  
          UIATarget.localTarget().frontMostApp().mainWindow().textFields()["User Text"];

            后一種方式更加清晰明了,應(yīng)該多使用。你可以通過Interface Builder設(shè)置UIAElement的name屬性,

            或者通過編寫代碼的方式:

          myTextField.accessibilityEnabled = YES; 
          myTextField.accessibilityLabel = @"User Text";

            你現(xiàn)在可以看到,通過accessibility屬性可以被UIAutomation用來找到不同的控件。這非常的清晰,因為,第一,你只要學(xué)習(xí)一個測試框架;第二,通過編寫自動化測試代碼,你同時還可以保證你的程序是可以被訪問的。因此,每一個UIAElement對象的子控件可以通過下面的方法進行訪問:

            buttons(), images(), scrollViews(),textFields(), webViews(), segmentedControls(), sliders(), staticTexts(), switches(), tabBar(),tableViews(), textViews(), toolbar(), toolbars() 等等……

            你可以通過如下代碼在tabbar上訪問第一個tab:

          var tabBar = UIATarget.localTarget().frontMostApp().tabBar(); 
          var tabButton = tabBar.buttons()["First"];

            UIAElement結(jié)構(gòu)層次非常的重要,你以后會常常用到它。而且你還要記住,你可以在隨時通過調(diào)用UIAAplication的logElementTree來獲得它的結(jié)構(gòu)。

          UIATarget.localTarget().frontMostApp().logElementTree();

            在模擬器上,你還可以激活A(yù)ccessibility 的檢測器。啟動模擬器,找到“Settings > General > Accessibility > Accessibility Inspector”,然后將它設(shè)為“打開”狀態(tài)。

            這個彩色的小框框就是Accessibility 檢測器了。當(dāng)它收起來的時候,Accessibility就被關(guān)閉了,當(dāng)它展開的時候,Accessibility就是打開的。你只要點擊上面的箭頭按鈕就可以激活或者屏蔽Accessibility。現(xiàn)在,打開我們的示例程序,激活檢測器。

            然后,點擊文本框,檢查UIAElement的name和value屬性(其實就是accessibilityLabel和accessibilityValue對應(yīng)的NSObject類型的值)。這個檢測器可以幫助你調(diào)試和編寫你的測試代碼。

          模擬用戶操作

            讓我們更進一步,模擬一些用戶的交互操作。你可以簡單地調(diào)用按鈕的tap()來作一個點擊操作:

          var tabBar = UIATarget.localTarget().frontMostApp().tabBar(); 
          var tabButton = tabBar.buttons()["First"];    
            
          // Tap the tab bar ! 
          tabButton.tap();

            你還可以調(diào)用UIAButtons的doubleTap(),twoFingerTap()。如果你不想操作具體的某個元素,你也可以直接根據(jù)屏幕上指定的坐標(biāo)點進行操作,你可以這么用:

            ● 點擊:

          UIATarget.localTarget().tap({x:100, y:200}); 
          UIATarget.localTarget().doubleTap({x:100, y:200}); 
          UIATarget.localTarget().twoFingerTap({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});

            注意,當(dāng)你指定操作的時間間隔的時候,它是有特定的范圍的,即:拖拽操作的時間間隔必須大于或者等于0.5秒,小于60秒。

            現(xiàn)在,讓我們來練習(xí)一下:

            1)停止Instruments (⌘R)

            2)在Scripts窗口里, 移除當(dāng)前的腳本

            3)點擊“Add > Import”然后選擇TestAutomation/TestUI/Test-1.js(將下面的代碼保存到這個路徑)

            4)點擊錄制按鈕 (⌘R) 然后看看將會發(fā)生什么…

            下面是Test-1.js代碼:

          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,并將上面的文本框的值設(shè)成“Unusually Long Name for a Recipe”,接著收起虛擬鍵盤。這里有一些新的方法值得注意的:UIATarget的delay(Number timeInterval) 方法允許你在兩個操作之間做一些等待,UIALogger的logMessage( String message) 方法用來將你想打印的信息輸出到日志上去,UIALogger的logPass(String message)方法指明你的測試腳本已經(jīng)成功的完成測試了。

            你還知道了如何訪問鍵盤上的按鈕,然后作點擊操作:

          app.keyboard().buttons()["return"].tap();

            由于時間有限且原文太長,先只能翻譯到這里,我會盡快的將剩下的部分翻譯補上。另外,時間倉促,如有翻譯得不準(zhǔn)確的地方,也敬請擔(dān)待。謝謝。



           

          posted on 2013-04-03 09:59 順其自然EVO 閱讀(739) 評論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄selenium and watir webdrivers 自動化測試學(xué)習(xí)

          <2013年4月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 沅陵县| 台安县| 沙湾县| 南投市| 文安县| 鄯善县| 兴化市| 凤台县| 荔浦县| 南投县| 喜德县| 萨迦县| 湘乡市| 旺苍县| 昭平县| 全椒县| 方山县| 蛟河市| 察雅县| 四会市| 奉贤区| 尉犁县| 萍乡市| 汪清县| 澄迈县| 多伦县| 潼南县| 宣汉县| 商水县| 中阳县| 乃东县| 和龙市| 延庆县| 奉节县| 和静县| 稷山县| 辽中县| 洪江市| 金平| 黎城县| 清河县|