一、概述
在Xcode中新建項目的時候會默認(rèn)勾選單元測試愕掏,勾選后每個XCode新建的iOS的項目中都有一個叫做”項目名Tests”的分組度秘,這個分組里就是XCTestCase的子類,XCTest中的測試類都是繼承自XCTestCase饵撑。當(dāng)我們?yōu)轫椖吭黾恿诵碌墓δ軙r敷钾,可以使用單元測試針對該模塊進(jìn)行測試。
二肄梨、單元測試的使用
1、常規(guī)測試
首先新建一個名為“MyDemo”的項目挠锥,我們會看到會自動生成如下的文件:
MyDemoTests中代碼為:
#import <XCTest/XCTest.h>
@interface MyDemoTests : XCTestCase
@end
@implementation MyDemoTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called 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.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
- (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
上面最重要的兩個方法為setUp和tearDown众羡,setUp方法在XCTestCase的測試方法調(diào)用之前調(diào)用。當(dāng)測試全部結(jié)束之后調(diào)用tearDown方法蓖租。上面的另外兩個方法是系統(tǒng)自動創(chuàng)建的功能測試用例的示例粱侣。我們可以自己創(chuàng)建測試方法,不過測試方法必須testXXX的格式蓖宦,且不能有參數(shù)齐婴,不然不會識別為測試方法。
setUp方法可以在測試之前創(chuàng)建在test case方法中需要用到的一些對象等稠茂。tearDown方法則在全部的test case執(zhí)行結(jié)束之后清理測試現(xiàn)場柠偶,釋放資源刪除不用的對象等情妖。
例如,我們?nèi)コ到y(tǒng)系統(tǒng)創(chuàng)建的兩個測試用例的示例诱担,我們自己創(chuàng)建一個方法:
#import <XCTest/XCTest.h>
@interface MyDemoTests : XCTestCase
@end
@implementation MyDemoTests
- (void)setUp {
[super setUp];
NSLog(@"setUp-----------------");
}
- (void)tearDown {
[super tearDown];
NSLog(@"tearDown-----------------");
}
- (void)testMyFun{
NSLog(@"testMyFun-----------------");
}
@end
按快捷鍵Command + U進(jìn)行單元測試毡证,打印結(jié)果(去除了其他暫不關(guān)注的打印):
2017-03-06 15:35:35.336 MyDemo[48088:5078800] setUp-----------------
2017-03-06 15:35:35.336 MyDemo[48088:5078800] testMyFun-----------------
2017-03-06 15:35:35.337 MyDemo[48088:5078800] tearDown-----------------
接下來我們新建一個類MyClass蔫仙,在MyClass中聲明和實現(xiàn)一個getNum的方法料睛,方法實現(xiàn)如下:
-(NSInteger)getNum{
return 5;
}
然后在我們MyDemoTests的testMyFun寫相關(guān)單元測試代碼(代碼中用到了斷言,斷言的使用后面再講):
#import <XCTest/XCTest.h>
#import "MyClass.h"
@interface MyDemoTests : XCTestCase
@end
@implementation MyDemoTests
- (void)setUp {
[super setUp];
NSLog(@"setUp-----------------");
}
- (void)tearDown {
[super tearDown];
NSLog(@"tearDown-----------------");
}
- (void)testMyFun{
NSLog(@"testMyFun-----------------");
MyClass *myClass = [[MyClass alloc]init];
NSInteger num = [myClass getNum];
XCTAssert(num < 10,@"num should less than 10");
}
@end
上面加了斷言摇邦,只有當(dāng)num<10的使用才能通過測試恤煞,由于此時num=5,所以可以順利通過測試施籍。
按快捷鍵Command + U進(jìn)行單元測試居扒,結(jié)果如下:
如果我們將getNum的返回結(jié)果改為15,則不會通過測試:
如果測試方法比較多的時候也可以直接點(diǎn)擊方法后運(yùn)行的圖標(biāo)單獨(dú)測試某個方法法梯,Command + U是全部測試:
2苔货、性能測試
剛開始的時候系統(tǒng)為我們創(chuàng)建的一個測試用例方法里有這么個方法:
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
測試代碼
- (void)testPerformanceExample {
NSLog(@"testPerformanceExample-----------------");
[self measureBlock:^{
MyClass *myClass = [[MyClass alloc]init];
[myClass getNum];
}];
}
按快捷鍵Command + U進(jìn)行單元測試,結(jié)果如下:
2017-03-06 16:42:01.403 MyDemo[51107:5178923] setUp-----------------
2017-03-06 16:42:01.404 MyDemo[51107:5178923] testPerformanceExample-----------------
/Users/lifengfeng/Desktop/Project/iOSProject/MyDemo/MyDemoTests/MyDemoTests.m:31: Test Case '-[MyDemoTests testPerformanceExample]' measured [Time, seconds] average: 0.422, relative standard deviation: 164.533%, values: [0.000053, 2.073384, 0.000010, 1.073334, 0.000013, 1.074108, 0.000016, 0.000005, 0.000004, 0.000003], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
2017-03-06 16:42:06.080 MyDemo[51107:5178923] tearDown-----------------
3立哑、常用的測試斷言
XCTFail(format) 生成一個失敗的測試;
XCTFail(@"Fail");
XCTAssertNil(a1, format…) 為空判斷夜惭, a1 為空時通過,反之不通過;
XCTAssertNil(@”not nil string”, @”string must be nil”);
XCTAssertNotNil(a1, format…) 不為空判斷铛绰,a1不為空時通過诈茧,反之不通過;
XCTAssertNotNil(@”not nil string”, @”string can not be nil”);
XCTAssert(expression, format…) 當(dāng)expression求值為TRUE時通過捂掰;
XCTAssert((2 > 2), @”expression must be true”);
XCTAssertTrue(expression, format…) 當(dāng)expression求值為TRUE時通過敢会;
XCTAssertTrue(1, @”Can not be zero”);
XCTAssertFalse(expression, format…) 當(dāng)expression求值為False時通過;
XCTAssertFalse((2 < 2), @”expression must be false”);
XCTAssertEqualObjects(a1, a2, format…) 判斷相等这嚣, [a1 isEqual:a2] 值為TRUE時通過鸥昏,其中一個不為空時,不通過姐帚;
XCTAssertEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return YES”);
XCTAssertNotEqualObjects(a1, a2, format…) 判斷不等吏垮, [a1 isEqual:a2] 值為False時通過,
XCTAssertNotEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return NO”);
XCTAssertEqual(a1, a2, format…) 判斷相等(當(dāng)a1和a2是 C語言標(biāo)量罐旗、結(jié)構(gòu)體或聯(lián)合體時使用,實際測試發(fā)現(xiàn)NSString也可以)膳汪;
XCTAssertNotEqual(a1, a2, format…) 判斷不等(當(dāng)a1和a2是 C語言標(biāo)量、結(jié)構(gòu)體或聯(lián)合體時使用);
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…) 判斷相等九秀,(double或float類型)提供一個誤差范圍遗嗽,當(dāng)在誤差范圍(+/- accuracy )以內(nèi)相等時通過測試;
XCTAssertEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return YES”);
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…) 判斷不等,(double或float類型)提供一個誤差范圍鼓蜒,當(dāng)在誤差范圍以內(nèi)不等時通過測試;
XCTAssertNotEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return NO”);
XCTAssertThrows(expression, format…) 異常測試痹换,當(dāng)expression發(fā)生異常時通過征字;反之不通過;
XCTAssertThrowsSpecific(expression, specificException, format…) 異常測試晴音,當(dāng)expression發(fā)生 specificException 異常時通過柔纵;反之發(fā)生其他異常或不發(fā)生異常均不通過;
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format…) 異常測試锤躁,當(dāng)expression發(fā)生具體異常搁料、具體異常名稱的異常時通過測試,反之不通過;
XCTAssertNoThrow(expression, format…) 異常測試系羞,當(dāng)expression沒有發(fā)生異常時通過測試郭计;
XCTAssertNoThrowSpecific(expression, specificException, format…) 異常測試,當(dāng)expression沒有發(fā)生具體異常椒振、具體異常名稱的異常時通過測試昭伸,反之不通過;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format…) 異常測試,當(dāng)expression沒有發(fā)生具體異常澎迎、具體異常名稱的異常時通過測試庐杨,反之不通過;