qileilove

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

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

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

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

            OCUnit

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

            ·添加單元測試

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

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

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

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

            

          圖3,添加Target不創(chuàng)建Scheme

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

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

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

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

            圖4,添加一個Application Tests

            ·創(chuàng)建測試用例

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

            1. - (void)setUp:每個test方法執(zhí)行前調(diào)用

            2. - (void)tearDown:每個test方法執(zhí)行后調(diào)用

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

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

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

            圖5,創(chuàng)建一個測試用例類

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

           Logic Tests與Application Tests的區(qū)別主要在setUp方法,Logic Tests只需在setUp方法中初始化一些測試數(shù)據(jù),而Application Tests需要在setUp方法中獲取主應(yīng)用的AppDelegate,供test方法調(diào)用。

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

            ·運行測試

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

            ·測試反饋

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

            GHUnit

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

            ·添加單元測試

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

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

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

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

            圖7,選擇GHUnitIOS.framework

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

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

            圖8,設(shè)置linker flags

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

            圖9,修改main函數(shù)

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

            圖10,單元測試App

          創(chuàng)建測試用例

            創(chuàng)建GHUnit測試用例與創(chuàng)建OCUnit測試用例相似。

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

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

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

            ·運行測試

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

            圖11,兩個用例的GHUnit App

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

            ·測試反饋

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

            圖12,未通過測試的方法,Console中的內(nèi)容

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

            總結(jié)

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

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

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


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


          網(wǎng)站導(dǎo)航:
           
          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 米脂县| 津市市| 沅江市| 阜新| 吴堡县| 微山县| 秦皇岛市| 合江县| 大荔县| 宝鸡市| 肥东县| 公安县| 西平县| 陕西省| 西盟| 关岭| 扎囊县| 黄平县| 贺州市| 大英县| 屯昌县| 兴化市| 乐都县| 兴宁市| 容城县| 襄城县| 大庆市| 赫章县| 靖江市| 县级市| 上栗县| 洛川县| 黄浦区| 甘德县| 手游| 乐亭县| 新余市| 灌云县| 台山市| 岳池县| 定陶县|