單元測試
- 以程序測試程序,以代碼測試代碼您访。測試每個功能是否正常運行铅忿。
AAA原則
- 在
Xcode
里面建立項目時,可以選擇Xcode
將我們的 App 建立單元測試的綁定灵汪。會出現(xiàn)一個繼承自XCTestCase
的類檀训,在里面編寫任何用test
開頭的方法柑潦,都是一條測試實例。也就是我們寫測試的時候峻凫,就是寫出一群用test
為開頭的方法渗鬼。- 擴展:
Xcode
從 5.1 版開始到現(xiàn)在的測試框架叫作XCTest
,在這之前是使用一套叫作OCUnit
的測試框架荧琼,除此之外譬胎,還有GHUnit、Kiwi等有名的測試框架铭腕。- AAA原則:在編寫測試的時候银择,基本原則就是一次只測試一項函數(shù)或方法多糠。同時一個
test
實例會包含所謂的 AAA 原則:Arrange
累舷、Act
、Assert
Arrange
:先設(shè)定我們在這次測試中夹孔,所預測的結(jié)果Act
:就是我們想要測試的函數(shù)或方法Assert
:確認在Act
發(fā)生后被盈,執(zhí)行了想要的函數(shù)或方法后,的確符合我們在Arrange
階段設(shè)定的目標搭伤。
- 比如:
- 在貪吃蛇游戲中只怎,預期一條長度為 6、正在往左邊移動的蛇怜俐,先往上移動一格身堡、再往右走一格、再往下走一格之后拍鲤,這條蛇的頭一定會撞到自己的身體贴谎,如果我們的程序說蛇頭沒有撞到,就一定有 bug季稳。就可以拆解成:
Arrange
:頭應(yīng)該會撞到身體Action
:讓蛇執(zhí)行往上右下移動的動作Assert
:確認蛇頭真的撞到身體了- (void)testHit
{
// 蛇對象
KKSnake *snake = [[KKSnake alloc]
initWithWorldSize:KKMakeSnakeWorldSize(10, 10) length:6];
// 蛇動作
[snake changeDirection:KKSnakeDirectionUp];[[snake move];
[snake changeDirection:KKSnakeDirectionRight];[snake move];
[snake changeDirection:KKSnakeDirectionDown];[snake move];
XCTAssertEqual([snake isHeadHitBody], YES, @"must hit the bo
dy.");
}
* 如果我們想要測試“蛇的尾巴加長”這段程序是否正常擅这,`思路:`原本這條蛇的長度為 2,尾巴位在`(6, 5)`,假如蛇的身體要加長兩格景鼠,預期舍得長度變成 4仲翎,尾巴為在`(8, 5)`. ```swift - (void)testIncreaseLength
{
ZBSnake *snake = [[ZBSnake alloc] initWithWorldSize:ZBMakeSn
akeWorldSize(10, 10) length:2];
XCTAssertEqual((int)[snake.points count], 2, @"Length must b
e 2 but %d", [snake.points count]);
NSInteger x;
NSInteger y;
x = [snake.points[[snake.points count] - 1] snakePointValue]
.x;
y = [snake.points[[snake.points count] - 1] snakePointValue]
.y;
XCTAssertEqual(x, 6, @"must be 6");
XCTAssertEqual(y, 5, @"must be 5");
[snake increaseLength:2];
XCTAssertEqual((int)[snake.points count], 4, @"Length must b
e 4 but %d", [snake.points count]);
x = [snake.points[[snake.points count] - 1] snakePointValue]
.x;
y = [snake.points[[snake.points count] - 1] snakePointValue]
.y;
XCTAssertEqual(x, 8, @"must be 8");
XCTAssertEqual(y, 5, @"must be 5");
}
執(zhí)行測試
- 寫了測試程序之后,我們可以在 Xcode 里面點擊
Product -> Test
執(zhí)行單元測試铛漓。如果XCTAssertEqual
這行assert
出現(xiàn)問題溯香,Xcode 就會立刻出現(xiàn)警告。- 在代碼的編輯頁面中浓恶,每一個
test
實例前方會出現(xiàn)一個菱形的標示逐哈,如果這個標示是空白的,代表還沒有執(zhí)行測試问顷。執(zhí)行完畢之后昂秃,如果成功禀梳,就會是綠色,反之就會變成紅色肠骆∷阃荆可以直接通過鼠標點擊此棱形標示,執(zhí)行測試蚀腿。
- 在 Xcode 的左側(cè)工具條的第四項嘴瓤,叫作
Test Navigator
,在這邊我們可以找到我們目前所在項目的所有test
實例,在這里可以看到每個test
實例是成功或失敗莉钙,也可以通過點擊廓脆,直接跳到特定test
的實例代碼。
- 在 Xcode 的左側(cè)工具條的最后一項磁玉,叫作
Report Navigator
停忿,可以看到最近一次完整執(zhí)行所有test
實例的結(jié)果。
測試驅(qū)動開發(fā)
Kent Beck
在2002年出版的書中提出測試驅(qū)動開發(fā)的概念:在開發(fā)軟件的時候蚊伞,我們不是先寫主要功能席赂,而是先寫測試。過程應(yīng)該是Red时迫、Green颅停、Refactor
三個階段:Red:
在還沒有主要功能前,先寫單元測試掠拳。由于主要功能都還沒有編寫癞揉,自然無法通過剛剛寫出來的單元測試,所以會亮出紅色的燈號溺欧。Green:
開始實現(xiàn)主要功能喊熟,直到可以通過單元測試,讓測試的燈號變成綠色胧奔。Refactor:
繼續(xù)整理寫出的代碼逊移。覆蓋率(Coverage)
- 所謂覆蓋率就是我們的單元測試覆蓋了程序的多少比例,也就是龙填,有多少程序被測試到胳泉、以及沒有被測試到。當我們發(fā)出有程序沒有被測試到之后岩遗,便進一步編寫跟多的
test
實例扇商,確保我們的程序經(jīng)過完整的測試。
- 在 Xcode7及以上版本中直接包含計算覆蓋率的功能宿礁。要在 Xcode 中展示覆蓋率案铺,首先是在
Scheme
中,勾選Gather Coverage Data
.
- 接著梆靖,在執(zhí)行單元測試的時候控汉,就可以看到有一個標示
Coverage
的分頁笔诵,標示每個項目的覆蓋率是多少。
- 選擇任意文件編輯姑子,便可以看到在頁面的最右方乎婿,可以看到每行程序在
test
實例中被執(zhí)行了數(shù)次,如果沒有執(zhí)行到(執(zhí)行次數(shù)為 0)街佑,背景就會變成紅色谢翎,提醒我們應(yīng)該要對這部分寫單元測試。