1.Given-When-Then分段
每個(gè)case其實(shí)都可以分為三步走,1.mock對(duì)象,準(zhǔn)備測(cè)試數(shù)據(jù)。2.調(diào)用目標(biāo)API 3.驗(yàn)證輸出和行為。所以我們可以用如下方式將3步分別放入Given-When-Then三個(gè)分段中。(為了保密,代碼做了改動(dòng))
- (void)testNeedToShowRowWhenTypeIsAll{
//given _sut.collectionType = 1;
NSIndexPath *path1 = [NSIndexPath indexPathForRow:1 inSection:1];
//when
BOOL needToShow1 = [_sut needToShowRow:path1]; //then
assertThatBool(needToShow1,isTrue());}
這樣我們一眼掃過(guò)去就可以清晰的看出一個(gè)case大體上都在干什么。
2.一個(gè)Case只測(cè)試一種情況
可能我們調(diào)用的一個(gè)API內(nèi)部有一個(gè)if…else…。我建議if一個(gè)case,else一個(gè)case。分兩個(gè)不同的case來(lái)作測(cè)試.這樣每個(gè)case就很清晰自己在測(cè)試什么東西。而如果全部雜糅在一個(gè)case中,可讀性會(huì)降低不少,而且case體積也會(huì)變得相對(duì)大很多,因?yàn)槟阋狦iven-When-Then兩次。更不建議在case中寫for循環(huán)驗(yàn)證。有人說(shuō)我的測(cè)試目標(biāo)函數(shù)中有很多if…else…,那么我覺(jué)得你應(yīng)該重構(gòu)下你的設(shè)計(jì)了。
所以,我們的結(jié)論是一個(gè)Case只測(cè)試一種情況,不同情況用When標(biāo)明:
- (void)testNeedToShowRowWhenTypeIsAll{
...
}
- (void)testNeedToShowRowWhenTypeIsOnSell{
...
}
3.用_sut來(lái)標(biāo)明被測(cè)試類
一個(gè)測(cè)試文件只有一個(gè)被測(cè)試類。但是當(dāng)我們的測(cè)試文件越來(lái)越多的時(shí)候,當(dāng)我們看一個(gè)測(cè)試case的時(shí)候需要看懂這個(gè)case才明白我們的被測(cè)試類是誰(shuí)?;蛘呶覀円部梢钥礈y(cè)試文件名(XXXXXXTest.m)才知道我們的被測(cè)試類是誰(shuí),但是這樣卻不是很直觀。所以不管我們?cè)谀莻€(gè)測(cè)試文件中,測(cè)試的類是誰(shuí),叫什么名字,我們都以為一個(gè)局部變量名_sut來(lái)定義我們的被測(cè)試類。這樣我們一眼就能知道我們被測(cè)試類是誰(shuí)。
_sut就是System Under Test的縮寫。
@implementation JHSCollectionDataSourceTest { JHSCollectionDataSource *_sut;
}
- (void)testNeedToShowHeaderWhenTypeIsAll{
//given
_sut.collectionType = 1;
//when
BOOL needToShow1 = [_sut needToShowHeader:1]; //then
assertThatBool(needToShow1,isTrue());
}
4.用Category暴露私有函數(shù)和屬性
我們的測(cè)試case中調(diào)用的方法可能會(huì)改變一個(gè)私有的屬性,調(diào)用一個(gè)私有的方法。怎么去優(yōu)雅的驗(yàn)證這種行為呢,我們可以在測(cè)試文件的開(kāi)頭用一個(gè)名字為UnitTest的category來(lái)暴露出我們的私有方法和屬性(屬性暴露的是屬性對(duì)應(yīng)的getter和setter方法)。
@interface JHSTestDataSource (UnitTest)
- (NSInteger)getSellGroupCount;
- (BOOL)needShowHeader:(NSInteger)section;
@end