qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          iOS開發中的單元測試(一)

            導讀:本文不討論單元測試是什么,或者它之于一個工程的利弊,我認為單元測試是一個開發者保證產出代碼質量的有效工具。本文從使用者的角度對比當下比較流行的兩款單元測試框架,給大家提供一些選用建議。如果你還不甚了解單元測試在工程中所起到的作用,或者還不知道TDD的開發模式,可參考:Test-Driven Development和Unit Testing。

            本文對比兩個iOS開發中常見的單元測試框架:OCUnit,被官方集成進XCode 4.x版本中;GHUnit,被推薦最多的測試框架,帶GUI界面。初窺兩款測試框架非常相似,而上手使用就會發現其中的區別。細節上的區別使兩款框架在不同角度各有優劣。

            OCUnit

            OCUnit是XCode 4.x集成的單元測試框架,OCUnit中的測試分為兩類,一類稱為Logic Tests,另一類稱為Application Tests。Logic Tests更傾向于所謂的白盒測試,用于測試工程中較細節的邏輯;Application Tests更傾向于黑盒測試,或接口測試,用于測試直接與用戶交互的接口。

            ·添加單元測試

            OCUnit是XCode集成的,所以其與工程的結合理應是最好的,添加到工程中的成本也理應最低。使用XCode創建新工程的流程中就有一個“Include Unit Tests”的選項(如圖1),新的工程就會自動生成一個Logic Tests。

            向已存在的工程中添加OCUnit Logic Tests也不復雜,只需要添加一個類型為:“Cocoa Touch Unit Testing Bundle”的Target即可(如圖2)。

          圖2,向已存在的工程中添加OCUnit測試

            向已有工程中添加一個測試Target時,XCode會自動生成一個Scheme,運行單元測試用例和Build原工程需要切換不同的Scheme。如果認為切換Scheme非常麻煩,也可以在添加Target之前,在“Manage Scheme”菜單中取消“Autocreate schemes”(如圖3)。

            

          圖3,添加Target不創建Scheme

            Application Tests要基于Logic Tests做一些修改。一般來說一個工程既需要Logic Tests也需要Application Tests,所以建議按照上述方法添加一個單獨的Target,然后執行以下操作(如圖4):

            1. 在Build Settings中搜索“bundle loader”,設置為:$(BUILT_PRODUCTS_DIR)/APP_NAME.app/APP_NAME(APP_NAME是應用名)

            2. 再搜索“test host”,設置為:$(BUNDLE_LOADER)

            3. 在Build Phases-Target Dependencies中添加依賴,選擇主程序Target

            圖4,添加一個Application Tests

            ·創建測試用例

            OCUnit的測試用例最常用的方法有三個

            1. - (void)setUp:每個test方法執行前調用

            2. - (void)tearDown:每個test方法執行后調用

            3. - (void)testXXX:命名為XXX的測試方法

            添加Target之時XCode已經自動創建了一個測試用例類:UnitTestDemoTests,其中UnitTestDemo是工程的名字,該類中已經包含了setUp,tearDown和testExample三個方法。

            通過command+n,選擇“Objective-C test case class”創建一個新的測試用例類(如圖5)。通過XCode創建的測試用例類是一個繼承自SenTestCase(OCUnit由SEN:TE公司開發,因此基類命名為SenTestCase)的空類,需要模仿UnitTestDemoTests編寫測試方法。

            圖5,創建一個測試用例類

            開發者可以自己實現無返回值,且命名規則為testXXX的實例方法,并使用框架提供的大量斷言方法。

           Logic Tests與Application Tests的區別主要在setUp方法,Logic Tests只需在setUp方法中初始化一些測試數據,而Application Tests需要在setUp方法中獲取主應用的AppDelegate,供test方法調用。

            值得注意的是,OCUnit的test bundle是侵入主應用的,因此在使用過程中要十分注意,不要讓單元測試的資源覆蓋主應用資源,造成詭異的Bug。

            ·運行測試

            由于OCUnit是集成在XCode中的框架,因此在XCode中運行也比較方便。切換到單元測試的scheme(如果與工程共用scheme則無需切換),Product->Test(或直接使用快捷鍵command+u),框架會自動查找所有工程中SenTestCase的子類,運行其中全部命名類似testXXX的無返回值方法。

            ·測試反饋

            OCUnit的失敗方法會通過Console和XCode Issues兩個位置反饋,通過XCode Issues可以直接定位到出現錯誤的單元測試代碼行。Issue的提示信息就是在單元測試斷言方法中定義的description。

            GHUnit

            GHUnit是一款Objective-C的測試框架,除了支持iOS工程還支持OSX的工程,但OSX不在本文的討論范圍。GHUnit不同于OCUnit,它提供了GUI界面來操作測試用例,而且也不區分Logic Tests和Application Tests。

            ·添加單元測試

            與集成進XCode的OCUnit相比,GHUnit的添加過程略顯復雜。首先在上下載GHUnit的框架包,當前的For iOS的最新版本是0.5.6,解壓后是一個GHUnitIOS.framework的文件夾。

            打開已經存在的工程,添加一個EmptyApplication Target,并在新Target中添加剛剛下載的GHUnitIOS.framework(如圖6、7)。

            圖6,在新Target中添加GHUnitIOS.framework

            在Build Phases中添加非官方框架并不會把框架文件拷貝到工程目錄,而是只做一個鏈接,所以建議在添加之前先把框架拷貝到工程目錄下。

            圖7,選擇GHUnitIOS.framework

            接下來用相同的方法添加框架依賴的其他庫:“QuartzCore.framework”。

            在Build Settings中搜索“linker flags”,設置Other Linker Flags - Debug - 添加一個支持全架構和全版本SDK的標示“-ObjC -all_load”(如圖8)。

            圖8,設置linker flags

            刪除Tests Target中的AppDelegate(.h和.m一起刪除)。修改main函數,支持GHUnitIOS,導入GHUnitIOSAppDelegate代替原來的AppDelegate,修改UIApplicationMain的參數(如圖9)。

            圖9,修改main函數

            至此已經完成了GHUnit的添加,選擇新建Target同時創建的scheme,直接Build and Run即可在設備或Simulator中啟動一個新的App(如圖10),即該單元測試的App。

            圖10,單元測試App

          創建測試用例

            創建GHUnit測試用例與創建OCUnit測試用例相似。

            新建一個Objective-C Class文件,繼承自GHTestCase,在XCode生成的.h文件中不會導入GHUnit.h文件,需要開發者自行導入“#import <GHUnitIOS/GHUnit.h>”。

            GHUnit框架提供斷言方法比OCUnit更加豐富,開發用例也就可以做的更加細致,更有利查找/定位錯誤。

            測試方法的命名規則與OCUnit一樣,是以test開頭的無返回值方法:- (void)testXXX。而常用的方法除了上述提到的setUp和tearDown,GHUnit還提供了setUpClass和tearDownClass兩個方法,在該用例運行前和結束后調用。另外,剛剛提到GHUnit不區分Logic Tests和Application Tests,所以在setUp和tearDown方法中也就不存在設置的區分。

            ·運行測試

            運行GHUnit需要分兩步,首先編譯并安裝單元測試App到設備或Simulator里(如圖11),創建了兩個用例,每個用例中分別有一個方法。

            圖11,兩個用例的GHUnit App

            在App中可以通過點擊右上角的Run按鈕運行全部用例,框架會查找所有以testXXX命名的無返回值方法,并執行。或點擊TableView中的某個Cell運行單獨的測試方法。

            ·測試反饋

            斷言失敗測試未通過的方法在App中會標記為紅色,并給出每一個方法的運行時間。在Console中會打印出詳細的出錯信息,包括:異常類型,出錯文件,位置,以及斷言方法中指定的出錯原因。更重要的是,出錯時的程序堆棧內容(如圖12)。

            圖12,未通過測試的方法,Console中的內容

            GHUnit通過Console中的內容給開發者提供幫助,可以快速定位程序出錯的位置,這一點比OCUnit做的要好。

            總結

            GHUnit在安裝上確實顯得有些麻煩,無法跟集成在XCode里的OCUnit相比。 但從開發者的角度講,我更喜歡GHUnit帶來的體驗,GUI的操作界面可以脫離IDE單獨運行,支持運行單一測試方法和運行全部用例的,打印出錯堆棧可以更快定位到問題所在。

            本文簡單介紹了兩款框架的安裝與入門,可以初步了解其各自特點,在接下來的文章中將會更加詳細的介紹如何使用框架進行單元測試,以及框架中的一些高級功能。此外,后續還將向大家介紹另外的與這兩款框架區別更加明顯的單元測試框架。

          posted on 2013-07-03 11:13 順其自然EVO 閱讀(214) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 清苑县| 革吉县| 麻江县| 江油市| 霍州市| 乐山市| 肃南| 临澧县| 军事| 中西区| 扶沟县| 建昌县| 小金县| 汕头市| 武功县| 通道| 双柏县| 屯门区| 松桃| 麻江县| 汕尾市| 二连浩特市| 辽宁省| 宁晋县| 韶关市| 萍乡市| 大同县| 休宁县| 铅山县| 仙居县| 琼海市| 清水河县| 哈巴河县| 临西县| 慈利县| 密云县| 馆陶县| 抚州市| 波密县| 宣化县| 漳浦县|