一惧笛、什么是UnitTest
在Xcode的API中這樣描寫(xiě):
The XCTest framework enables you to write unit tests for your Xcode projects that integrate seamlessly with the Xcode testing workflow, as described in Testing with Xcode.
Tests assert that certain conditions are satisfied during test execution, and record test failures (with optional messages) if those conditions are not satisfied. Tests can also measure the performance of blocks of code to check for performance regressions, and can interact with an application's UI to validate user interaction flows.
總結(jié)來(lái)說(shuō)就是針對(duì)代碼模塊:1、測(cè)試代碼是否滿足某些條件赢乓,如果不滿足松忍,則記錄失敽们峰锁;2回还、測(cè)試代碼模塊性能(測(cè)試代碼執(zhí)行花費(fèi)的時(shí)間);3戏蔑、驗(yàn)證UI交互(這部分屬于UITest暫且不討論蹋凝,實(shí)用性太差)
二、什么時(shí)候使用UnitTest
iOS UnitTest最大的好處是总棵,我們可以不運(yùn)行我們的工程而測(cè)試我們想要測(cè)試的代碼鳍寂,并且可以做到批量測(cè)試,對(duì)于APP來(lái)講情龄,我們可以就免去了多個(gè)頁(yè)面的點(diǎn)擊迄汛,以及覆蓋問(wèn)題。最明顯的就是接口測(cè)試骤视,我們可以可以做到一鍵測(cè)試所有接口(事實(shí)上并不是真的一鍵鞍爱,我們還是需要配置每個(gè)需要測(cè)試的接口,但是一次配置专酗,就可以做到一勞永逸)是否完好睹逃。在我們的接口改變,新增等情況下祷肯,我們不但需要對(duì)新增的接口測(cè)試唯卖,還需要查看老接口是否受影響的情況下粱玲,UnitTest就顯示十分方便。
對(duì)于接口測(cè)試拜轨,屬于我們前文所提到的“測(cè)試代碼是否滿足某些條件”抽减,這個(gè)方法還可以檢查我們的代碼邏輯,譬如我們工程里有本地計(jì)算訂單費(fèi)用橄碾,積分等卵沉,都可以用這個(gè)思想進(jìn)行測(cè)試。
測(cè)試代碼模塊性能:我們可以用以測(cè)試代碼運(yùn)行花費(fèi)時(shí)間法牲,block執(zhí)行時(shí)間史汗。當(dāng)我們有下載需求,比如捕手中的二維碼保存拒垃,可以大致打估出所需時(shí)間(不太實(shí)用停撞,對(duì)下載最大影響還是網(wǎng)速)。
三悼瓮、UnitTest的使用
1戈毒、創(chuàng)建
第一個(gè)方法是在創(chuàng)建工程時(shí)勾選Include Unit Test
或者在創(chuàng)建工程以后,再添加target
這時(shí)候横堡,我們可以看到工程里多了一個(gè)Tests文件夾埋市,里面包含一個(gè)一個(gè)Test文件,
這就是我們的unitTest文件命贴,當(dāng)然道宅,我們也可以自己再創(chuàng)建多個(gè),以此來(lái)區(qū)分測(cè)試不同的模塊胸蛛。
可以看到.m文件初始包含4個(gè)方法
1)setUp:所有測(cè)試方法執(zhí)行之前都會(huì)執(zhí)行這個(gè)方法污茵,如果我們需要確定一個(gè)對(duì)象的方法,可現(xiàn)在這個(gè)方法里實(shí)例化對(duì)象葬项。
2)tearDown:所有測(cè)試方法執(zhí)行之后都會(huì)執(zhí)行這個(gè)方法
3)testExample:一個(gè)測(cè)試用例泞当,里面可以寫(xiě)測(cè)試代碼,我們自己寫(xiě)測(cè)試方法玷室,都以test開(kāi)頭零蓉,才會(huì)有自動(dòng)執(zhí)行
4)testPerformanceExample:里面的measureBlock內(nèi)為性能測(cè)試笤受,測(cè)試一段代碼執(zhí)行時(shí)常穷缤。
2、使用
我們先來(lái)看XCTest自帶的斷言:
XCTAssertNotNil(a1, format…) 當(dāng)a1不為nil時(shí)成立
XCTAssert(expression, format...) 當(dāng)expression結(jié)果為YES成立
XCTAssertTrue(expression, format...) 當(dāng)expression結(jié)果為YES成立箩兽;
XCTAssertEqualObjects(a1, a2, format...) 判斷相等津肛,當(dāng)[a1 isEqualTo: a2]返回YES的時(shí)候成立
XCTAssertEqual(a1, a2, format...) 當(dāng)a1==a2返回YES時(shí)成立
XCTAssertNotEqual(a1, a2, format...) 當(dāng)a1!=a2返回YES時(shí)成立
&&
XCTFail(format…) 生成一個(gè)失敗的測(cè)試;
XCTAssertNil(a1, format...)為空判斷汗贫,a1為空時(shí)通過(guò)身坐,反之不通過(guò)秸脱;
XCTAssertNotNil(a1, format…)不為空判斷,a1不為空時(shí)通過(guò)部蛇,反之不通過(guò)摊唇;
XCTAssert(expression, format...)當(dāng)expression求值為T(mén)RUE時(shí)通過(guò);
XCTAssertTrue(expression, format...)當(dāng)expression求值為T(mén)RUE時(shí)通過(guò)涯鲁;
XCTAssertFalse(expression, format...)當(dāng)expression求值為False時(shí)通過(guò)巷查;
XCTAssertEqualObjects(a1, a2, format...)判斷相等,[a1 isEqual:a2]值為T(mén)RUE時(shí)通過(guò)抹腿,其中一個(gè)不為空時(shí)岛请,不通過(guò);
XCTAssertNotEqualObjects(a1, a2, format...)判斷不等警绩,[a1 isEqual:a2]值為False時(shí)通過(guò)崇败;
XCTAssertEqual(a1, a2, format...)判斷相等(當(dāng)a1和a2是 C語(yǔ)言標(biāo)量、結(jié)構(gòu)體或聯(lián)合體時(shí)使用, 判斷的是變量的地址肩祥,如果地址相同則返回TRUE后室,否則返回NO);
XCTAssertNotEqual(a1, a2, format...)判斷不等(當(dāng)a1和a2是 C語(yǔ)言標(biāo)量搭幻、結(jié)構(gòu)體或聯(lián)合體時(shí)使用)咧擂;
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判斷相等,(double或float類(lèi)型)提供一個(gè)誤差范圍檀蹋,當(dāng)在誤差范圍(+/-accuracy)以內(nèi)相等時(shí)通過(guò)測(cè)試松申;
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判斷不等,(double或float類(lèi)型)提供一個(gè)誤差范圍俯逾,當(dāng)在誤差范圍以內(nèi)不等時(shí)通過(guò)測(cè)試贸桶;
XCTAssertThrows(expression, format...)異常測(cè)試,當(dāng)expression發(fā)生異常時(shí)通過(guò)桌肴;反之不通過(guò)皇筛;(很變態(tài)) XCTAssertThrowsSpecific(expression, specificException, format...) 異常測(cè)試,當(dāng)expression發(fā)生specificException異常時(shí)通過(guò)坠七;反之發(fā)生其他異乘祝或不發(fā)生異常均不通過(guò);
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)異常測(cè)試彪置,當(dāng)expression發(fā)生具體異常拄踪、具體異常名稱(chēng)的異常時(shí)通過(guò)測(cè)試,反之不通過(guò)拳魁;
XCTAssertNoThrow(expression, format…)異常測(cè)試惶桐,當(dāng)expression沒(méi)有發(fā)生異常時(shí)通過(guò)測(cè)試;
XCTAssertNoThrowSpecific(expression, specificException, format...)異常測(cè)試,當(dāng)expression沒(méi)有發(fā)生具體異常姚糊、具體異常名稱(chēng)的異常時(shí)通過(guò)測(cè)試贿衍,反之不通過(guò);
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)異常測(cè)試救恨,當(dāng)expression沒(méi)有發(fā)生具體異常贸辈、具體異常名稱(chēng)的異常時(shí)通過(guò)測(cè)試,反之不通過(guò)
用一個(gè)XCTAssertTrue舉例來(lái)說(shuō)肠槽,可以看出這個(gè)函數(shù)是判斷是否為真裙椭。比如我們做出XCTAssertTrue(3>5)的判斷,為結(jié)果正確署浩,測(cè)試會(huì)順利通過(guò)揉燃,假如XCTAssertTrue(3>5),結(jié)果為假筋栋,便會(huì)報(bào)錯(cuò)炊汤,并展示我們所添加說(shuō)明。我們可以寫(xiě)一段代碼測(cè)試一下:
在以test開(kāi)頭的方法左邊弊攘,我們可以看到一個(gè)菱形的標(biāo)志抢腐,點(diǎn)擊就可以運(yùn)行這段測(cè)試代碼,也可以command + U執(zhí)行所有測(cè)試代碼襟交,還可以如圖所示迈倍,點(diǎn)擊工程右邊的執(zhí)行鍵,或者模塊的捣域,或者指定方法的:
運(yùn)行結(jié)果:
報(bào)錯(cuò)了啼染,如果我們執(zhí)行了所有測(cè)試代碼,這時(shí)候我們可以在Xcode界面里看到所有的測(cè)試代碼的運(yùn)行加過(guò)焕梅,成功的會(huì)有對(duì)號(hào)迹鹅,錯(cuò)誤的會(huì)報(bào)錯(cuò),錯(cuò)誤的測(cè)試代碼并會(huì)不影響其他的方法贞言,這樣我們可以方便的查看所有出問(wèn)題的代碼斜棚,如下圖所示。
接著看上面這張圖该窗,可以看到我在setUp方法里弟蚀,實(shí)例化了一個(gè)ViewController。我在ViewController寫(xiě)了一個(gè)簡(jiǎn)單的A-B求值的方法酗失,我們可以寫(xiě)在XCTAssertTrue里測(cè)試:
我們接著看上面的大圖义钉,可以看到下面的testExample方法,我們進(jìn)行了網(wǎng)絡(luò)請(qǐng)求的測(cè)試级零。
在這里断医,測(cè)試方法是異步執(zhí)行,我們可以設(shè)置期望奏纪,來(lái)設(shè)定我們期望的時(shí)間鉴嗤。
我們?cè)趧?chuàng)建expectation時(shí),可以加入錯(cuò)誤描述序调,比如我們這個(gè)網(wǎng)絡(luò)請(qǐng)求醉锅,我在waitForExpectationsWithTimeout設(shè)置了時(shí)間為3,在expectationWithDescription設(shè)定的問(wèn)題描述是超時(shí)发绢,當(dāng)我們的這個(gè)網(wǎng)絡(luò)請(qǐng)求超過(guò)3秒鐘硬耍,在waitForExpectationsWithTimeout就會(huì)報(bào)錯(cuò),錯(cuò)誤描述就會(huì)有我們的問(wèn)題描述边酒,在看我請(qǐng)求成功里寫(xiě)的经柴,XCTAssertNotNil(responseObject, @“返回出錯(cuò)”),XCTAssertNotNil判斷里面的對(duì)象不為nil墩朦,如果是nil則報(bào)錯(cuò)坯认,展示返回錯(cuò)誤。參考:XCTest的waitForExpectationsWithTimeout 方法
接下來(lái)我們看下面這個(gè)方法
描述為性能測(cè)試氓涣,我們可以把自己需要測(cè)試的方法放到block里牛哺,block里的代碼,會(huì)執(zhí)行10次劳吠,取出平均值引润,比如我們?cè)谶@里打印1000次,點(diǎn)擊旁邊的菱形運(yùn)行
我們可以看到痒玩,右邊的測(cè)試結(jié)果展示了這段代碼執(zhí)行所用的時(shí)間淳附,這是簡(jiǎn)單應(yīng)用,我們可以測(cè)試ViewController的代碼性能蠢古。
接下來(lái)點(diǎn)擊左邊的灰色菱形燃观,在這里可以看到這十次執(zhí)行的每次執(zhí)行時(shí)間,
在這里我們點(diǎn)擊set Baseline 可以設(shè)定我們的逾期便瑟,
比如我們?cè)O(shè)定逾期時(shí)間為 0.100S
然后執(zhí)行這段代碼缆毁,
可以看到,報(bào)錯(cuò)了到涂,并且告訴我們脊框,這段打碼執(zhí)行時(shí)間超出了我們超出的程度。
參考資料:http://blog.csdn.net/jeikerxiao/article/details/51668655