單元測試測試什么
對象一般都具有一定的狀態(tài)院促,我們寫的每一個方法党晋,要么會產(chǎn)生一個或者多個輸出,要么會改變一個或者多個對象的狀態(tài)哮翘,或者兼而有之颈嚼。如果一個方法既沒有輸出,也沒有改變?nèi)魏螌ο蟮臓顟B(tài)饭寺,那么這個方法是不必要存在的阻课。
單元測試主要測試的是一個類對外暴露的方法,通過執(zhí)行一個或者多個方法艰匙,來檢測對象的狀態(tài)或者輸出結(jié)果是否與預(yù)期一致限煞。
單元測試需要注意一下幾點:
- 盡量避免直接測試私有方法,當(dāng)私有方法過于復(fù)雜時员凝,應(yīng)該考慮重構(gòu)代碼署驻,將私有方法封裝的邏輯轉(zhuǎn)移到另一個對象中,成為公有方法健霹。
- 因為單元測試是基于有特定對象的旺上,所以無法測試構(gòu)造函數(shù)。當(dāng)構(gòu)造函數(shù)中包含復(fù)雜的邏輯時糖埋,需要重構(gòu)宣吱,將其移動到某個方法中。當(dāng)構(gòu)造函數(shù)中包含其他對象的創(chuàng)建邏輯時瞳别,將這個對象作為構(gòu)造函數(shù)的參數(shù)傳入征候。
- 單元測試覆蓋率不必要達(dá)到100%,因為覆蓋率越高祟敛,預(yù)期收益越低倍奢,對于那些特別簡單的邏輯或者單元測試無法驗證的邏輯可以不用測試,比如生成訂單號的邏輯垒棋,我們通過單元測試無法驗證生成的訂單號是否是唯一的卒煞,所以不必要做單元測試。
如何設(shè)計單元測試用例
Arrange(準(zhǔn)備)->Act(執(zhí)行)->Assert(斷言)
- 準(zhǔn)備階段:定義待測試的對象叼架,準(zhǔn)備合適的測試參數(shù)
- 執(zhí)行階段:執(zhí)行待測試的一個或者多個方法
- 斷言階段:檢測方法的輸出或者對象的狀態(tài)是否符合預(yù)期
比如對于方法計算最大公約數(shù)的代碼:
// Class: GCDCalculator
- (NSUInteger)GCDWithNumber1:(NSUInteger)number1 number2:(NSUInteger)number2 {
NSUInteger remainder = number1 % number2;
if (remainder == 0) {
return number2;
} else {
return [self GCDWithNumber1:number2 number2:remainder];
}
}
在準(zhǔn)備階段畔裕,我們需要創(chuàng)建一個GCDCalculator的對象,然后設(shè)計好合適的測試參數(shù)乖订,比如10和6
在執(zhí)行階段扮饶,我們調(diào)用方法-[CGCDCalculator GCDWithNumber1: number2:]
得到一個結(jié)果
在斷言階段,我們驗證這個結(jié)果是否與我們預(yù)期的2一致
- (void)testGCD {
// Arrange
GCDCalculator *cal = [[GCDCaculator alloc] init];
// Act
NSUInteger gcd = [cal GCDWithNumber1:10 number2:6];
// Assert
XCTAssertEqual(gcd, 2, @"GCD failed");
}