iOS 單元測(cè)試之XCTest詳解

參考自:?iOS 單元測(cè)試之XCTest詳解

原創(chuàng)blog,轉(zhuǎn)載請(qǐng)注明出處?

blog.csdn.net/hello_hwc?

歡迎關(guān)注我的iOS-SDK詳解專欄?

http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html

前言:測(cè)試是一個(gè)好的App不可缺少的部分。每一個(gè)App都是由一個(gè)個(gè)小的功能組合到一起的。而這些小的功能又是由一個(gè)個(gè)函數(shù)或者說算法組合到一起的。單元測(cè)試就是對(duì)這些小的功能或者函數(shù)進(jìn)行測(cè)試,良好的單元測(cè)試會(huì)讓代碼的健壯性提高很多。XCTest就是XCode為我們提供的一個(gè)框架,它提供了各個(gè)層次的測(cè)試。

XCTestCase

每個(gè)XCode創(chuàng)建iOS的工程中都有一個(gè)叫做”工程名Tests”的分組,這個(gè)分組里就是XCTestCase的子類,XCTest中的測(cè)試類都是繼承自XCTestCase。?

例如新建一個(gè)工程,命名為Demo,就能看到如圖?


看一下這個(gè)自動(dòng)創(chuàng)建的文件里都包含了哪些內(nèi)容

#import ?

@interface?DemoTests : XCTestCase?

@end

?@implementation?DemoTests

- (void)setUp {

????[super?setUp];?

????//?Put setup code here. This method?iscalled before the invocation?of?each test method?in?the?class.

?}

- (void)tearDown {?

????//?Put teardown code here. This method?is?called after the invocation?of?each test method?in?the?class.?

????[super?tearDown];

}

- (void)testExample {?

????//?This?is?an example?of?a functional test?case.

????XCTAssert(YES, @"Pass");

}

- (void)testPerformanceExample {?

????//?This?is?an example?of?a performance test?case. [self?measureBlock:^{?

????//?Put the code you want to measure the time?of?here. }];

}

?@end

測(cè)試用例的命名

XCTest中所有的測(cè)試用例的命名都是以test開頭的。例如上文中的

- (void)testExample {

//?This?is?an example?of?a functional test?case.

????XCTAssert(YES, @"Pass");

}

setUp和tearDown

Setup是在所有測(cè)試用例運(yùn)行之前運(yùn)行的函數(shù),在這個(gè)測(cè)試用例里進(jìn)行一些通用的初始化工作

tearDown是在所有的測(cè)試用例都執(zhí)行完畢后執(zhí)行的

XCode的測(cè)試用例導(dǎo)航

測(cè)試用例的導(dǎo)航如圖,在測(cè)試用例的導(dǎo)航里,我們可以運(yùn)行一組測(cè)試用例,也可以運(yùn)行一個(gè)單獨(dú)的測(cè)試用例?

可以鼠標(biāo)右鍵來新建一組測(cè)試用例。?

也可以為測(cè)試用例添加失敗斷點(diǎn)來方便我們調(diào)試?

查看測(cè)試結(jié)果

通過測(cè)試導(dǎo)航欄可以查看到測(cè)試結(jié)果

通過Report導(dǎo)航欄可以看到更詳細(xì)的測(cè)試結(jié)果

點(diǎn)擊測(cè)試用例后面的箭頭,可以跳轉(zhuǎn)到測(cè)試用例的代碼。

普通方法測(cè)試

例如,新建一個(gè)類命名為Model,他有這個(gè)方法用來生成10以內(nèi)的隨機(jī)數(shù)。

- (NSInteger)randomLessThanTen{

????return arc4random()%10;

}

于是,測(cè)試方法為

-(void)testModelFunc_randomLessThanTen{

????Model * model = [[Model alloc] init];

????NSInteger num = [model randomLessThanTen];

????XCTAssert(num<10,@"num should less than 10");

}

我們點(diǎn)擊如圖的左邊圖標(biāo)單獨(dú)運(yùn)行這個(gè)測(cè)試用例,當(dāng)然也可以在上文我提到的導(dǎo)航欄里單獨(dú)運(yùn)行。?


然后會(huì)看到輸出表示這個(gè)測(cè)試用例通過

Test Suite?'Selected tests'?started?at?2015-06-28?05:24:56?+0000?

Test Suite?'DemoTests.xctest'?started?at?2015-06-28?05:24:56?+0000?

Test Suite?'DemoTests'?started?at?2015-06-28?05:24:56?+0000?

Test Case?'-[DemoTests testModelFunc_randomLessThanTen]'?started.

Test Case?'-[DemoTests testModelFunc_randomLessThanTen]'?passed (0.000?seconds).

Test Suite?'DemoTests'?passed?at?2015-06-28?05:24:56?+0000.?Executed?1?test,?with?0?failures (0?unexpected)?in?0.000?(0.001)?seconds?

Test Suite?'DemoTests.xctest'?passed?at?2015-06-28?05:24:56?+0000.?Executed?1?test,?with?0?failures (0?unexpected)?in?0.000?(0.001)?seconds?

Test Suite?'Selected tests'?passed?at?2015-06-28?05:24:56?+0000.

常用斷言

如何判斷一個(gè)測(cè)試用例成功或者失敗呢?XCTest使用斷言來實(shí)現(xiàn)。?

最基本的斷言?

表示如果expression滿足,則測(cè)試通過,否則對(duì)應(yīng)format的錯(cuò)誤。

XCTAssert(expression,?format...)

還有一個(gè)用來直接Fail的斷言

XCTFail(format...)

其他一些常用的斷言:

XCTAssertTrue(expression,?format...)

XCTAssertFalse(expression,?format...)

XCTAssertEqual(expression1, expression2,?format...)

XCTAssertNotEqual(expression1, expression2,?format...)

XCTAssertEqualWithAccuracy(expression1, expression2, accuracy,?format...)

XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy,?format...)

XCTAssertNil(expression,?format...) XCTAssertNotNil(expression,?format...)

性能測(cè)試

所謂性能測(cè)試,主要就是評(píng)估一段代碼的運(yùn)行時(shí)間,XCTest的性能的測(cè)試?yán)萌缦赂袷?/p>

對(duì)于性能測(cè)試,每一個(gè)測(cè)試用例每次會(huì)運(yùn)行10次。

- (void)testPerformanceExample {?

????/?This?is?an example?of?a performance test?case.

????[self?measureBlock:^{?

????/?Put the code you want to measure the time?of?here.

????}];

}

例如,我要評(píng)估一段代碼,循環(huán)打印NSLog 10000次。?

這段代碼如下,這段代碼我放在UIImage的類別里。

- (void)testPerformanceExample {?

????// This is an example of a performance test case.

?????[self measureBlock:^{?

????????for?(NSInteger?index?=?0;?index?<?10000;?index?++) {

????????????NSLog(@"%ld",index);

????????}?

????????// Put the code you want to measure the time of here.?

????}];

}

我們都知道,測(cè)試要么成功,要么失敗,那么就引入了一個(gè)關(guān)鍵的問題

性能測(cè)試的時(shí)候,如何判一個(gè)性能測(cè)試case是成功還是失敗呢?

我們先通過上文的方式,只運(yùn)行一次這個(gè)測(cè)試用例。然后看看結(jié)果和輸出(這個(gè)測(cè)試用例跑的很慢,別著急)

Test Case?'-[ModelTests testPerformanceExample]'?failed (37.432?seconds).

Test Suite?'ModelTests'?failed?at?2017-02-19?09:57:26.210. Executed?1?test,?with?1?failure (0?unexpected)?in?37.432?(37.433)?seconds

?Test Suite?'ToDoTests.xctest'?failed?at?2017-02-19?09:57:26.211. Executed?1?test,?with?1?failure (0?unexpected)?in?37.432?(37.434)?seconds

?Test Suite?'Selected tests'?failed?at?2017-02-19?09:57:26.211. Executed?1?test,?with?1?failure (0?unexpected)?in?37.432?(37.437)?seconds?

Test session?log: /Users/hl/Library/Developer/Xcode/DerivedData/ToDo-bbcdkwvzbmyznocgystdcavfakca/Logs/Test/98E0FA82-BACC-4361-AF39-E0734F73A545/Session-ToDoTests-2017-02-19_095641-jm2eKF.log

然后,你會(huì)發(fā)現(xiàn)測(cè)試失敗了!這是因?yàn)槲覀儧]有給性能測(cè)試一個(gè)參考時(shí)間。?

我們點(diǎn)擊圖中的的第二個(gè)叉箭頭

然后,看到如圖?

我們來看看這幾個(gè)參數(shù)都是啥意思:

Baseline 計(jì)算標(biāo)準(zhǔn)差的參考值

MAX STDD 最大允許的標(biāo)準(zhǔn)差

底部點(diǎn)擊1,2…10可以看到每次運(yùn)行的結(jié)果。

點(diǎn)擊Edit,我們點(diǎn)擊Average的右邊的Accept,來讓本次運(yùn)行的平均值設(shè)置為baseline,然后然后MAX STDD改為40%。再運(yùn)行這個(gè)測(cè)試用例,你會(huì)發(fā)現(xiàn)測(cè)試成功了。

異步測(cè)試

異步測(cè)試的邏輯如下,首先定義一個(gè)或者多個(gè)XCTestExpectation,表示異步測(cè)試想要的結(jié)果。然后設(shè)置timeout,表示異步測(cè)試最多可以執(zhí)行的時(shí)間。最后,在異步的代碼完成的最后,調(diào)用fullfill來通知異步測(cè)試滿足條件。

- (void)testAsyncFunction{?

????XCTestExpectation?* expectation = [self?expectationWithDescription:@"Just a demo ????expectation,should pass"];?

????//Async?function?when?finished call

????[expectation fullfill];

????[self?waitForExpectationsWithTimeout:10?handler:^(NSError?*error) {?//Do?something?when?time out }]; }

舉例

- (void)testAsyncFunction{

????XCTestExpectation * expectation = [self?expectationWithDescription:@"Just a demo expectation,should pass"];

? ?dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0), ^{ ????????sleep(1);?

????????NSLog(@"Async test");

????????XCTAssert(YES,"should pass");

????????[expectation fulfill];

????});

????[self?waitForExpectationsWithTimeout:10?handler:^(NSError?*error) {?

????????//Do something when time out

?????}];

}

測(cè)試結(jié)果

Test Suite?'Selected tests'?started?at?2015-06-28?05:49:43?+0000?

Test Suite?'DemoTests.xctest'?started?at?2015-06-28?05:49:43?+0000?

Test Suite?'DemoTests'?started?at?2015-06-28?05:49:43?+0000?

Test Case?'-[DemoTests testAsyncFunction]'?started.?2015-06-28?13:49:44.920

?Demo[2157:145428] Async test Test Case?'-[DemoTests testAsyncFunction]'?passed (1.006?seconds). Test Suite?'DemoTests'?passed?at?2015-06-28?05:49:44?+0000.?Executed?1?test,?with?0?failures (0?unexpected)?in?1.006?(1.007)?seconds?

Test Suite?'DemoTests.xctest'?passed?at?2015-06-28?05:49:44?+0000.?Executed?1?test,?with?0?failures (0?unexpected)?in?1.006?(1.009)?seconds?

Test Suite?'Selected tests'?passed?at?2015-06-28?05:49:44?+0000.

代碼覆蓋率

選擇Target,然后選擇Test模塊,然后勾選Gather coverage data

然后,在report模塊中,就能看到每一個(gè).m文件的代碼覆蓋情況了。

后續(xù):

更新:2017.02.19 增加代碼覆蓋率,對(duì)性能測(cè)試進(jìn)行詳細(xì)的講解。

計(jì)劃下一篇會(huì)講解Mock 測(cè)試以及一些常用的Mock小工具。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言:測(cè)試是一個(gè)好的App不可缺少的部分。每一個(gè)App都是由一個(gè)個(gè)小的功能組合到一起的。而這些小的功能又是由一個(gè)個(gè)...
    伯牙呀閱讀 6,849評(píng)論 1 19
  • 前言:測(cè)試是一個(gè)好的App不可缺少的部分。每一個(gè)App都是由一個(gè)個(gè)小的功能組合到一起的。而這些小的功能又是由一個(gè)個(gè)...
    廖丹_18be閱讀 756評(píng)論 0 1
  • 關(guān)于iOS的UI自動(dòng)化測(cè)試,是從Xcode7之后才支持的比較好,使用XCTest.framework,Xcode可...
    房小房MT閱讀 5,502評(píng)論 4 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,533評(píng)論 19 139
  • 轉(zhuǎn):http://www.itdecent.cn/p/d5fca0185e83 Xcode測(cè)試 前言 總算在今天把...
    測(cè)試小螞蟻閱讀 3,356評(píng)論 0 20

友情鏈接更多精彩內(nèi)容