亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

[iOS翻譯]《iOS7byTutorials》系列:在Xcode5里使用單元測試(上)

2019-11-14 20:24:41
字體:
來源:轉載
供稿:網友

簡介:

單元測試是軟件開發的一個重要方面。畢竟,單元測試可以幫你找到bug和崩潰原因,而程序崩潰是Apple在審查時拒絕app上架的首要原因。

單元測試不是萬能的,但Apple把它作為開發工具包的一部分,不僅讓你創作的APP更穩定,而且提供了一致、有趣的用戶體驗,這些都是讓用戶給你五星評價的源泉!iOS7提供了一個升級的單元測試框架,讓你在Xcode中運行單元測試更為容易。當你完成這一章節,你將學會如何給現有app添加測試——并有可能培養出對編寫測試的熱愛!

/*

本文翻譯自《iOS7 by Tutorials》一書的第十一章“Unit Testing in Xcode 5”,想體會原文精髓的朋友請到Raywenderlich商店支持正版。

——————(博客園、新浪微博)葛布林大帝

*/

 

目錄:

一、單元測試基礎

二、開始項目

三、下一步何去何從?

四、挑戰

附錄:XCTest斷言參考

 

一、單元測試基礎

在過去,Xcode引入了一個叫做OCUnit的開源單元測試框架。而在Xcode 5里面,Apple發布了他們自己的的單元測試框架,叫做XCTest。

如果你已經熟悉OCUnit,別擔心,XCTest是一個建立在OCUnit之上并且十份相似的API。從OCUnit過渡到XCTest非常簡單,要做的僅僅是把STFail替換為XCTFail、STAssert替換為XCTAssert等等諸如此類。如果你已經熟悉這些基礎,可以直接跳到下一節。

 

 

1.高層次概述

 

 單元測試有四個層級。從上到下,它們分別是:

 

  • 測試套件(Test suite)
    • 這是項目里測試的全部集合。在Xcode里,測試套件被設置為一個單獨的build target。
  • 測試用例類(Test case classes)
    • 正如你可能所期待的,在一個面向對象體系中,測試被整合到類里。在你的app里,每個測試類通常對應一個單獨類。例如,DeveloperTests類應該對應Developer類的測試。
  • 測試用例方法(Test case methods)
    • 每個測試類包含多種方法,用來測試類的各種功能。就像一個方法或函數應該既精簡又實用,每個測試用例應該測試一個特定的結果——并且完全測試。
  • 斷言(Assertions)
    • 斷言檢查對應預期結果的具體條件。如果條件不符合預期結果, Xcode會報錯指出斷言失敗。例如,可以斷言你的Developer 類響應“writeKillerApp: message”;如果它沒有,斷言失敗,Xcode報錯。

 

 

理論很美好,但有時舉例會更容易闡述事物。用Empty application 模板創建一個新項目,命名為EmptyApp。 Xcode模板會自動包含一個叫做EmptyAPPTests的test target,添加到EmptyApp的 app target里,如下圖:

 

注意測試用例類包含了一個沒有關聯頭文件的.m文件,打開EmptyAppTests.m看看第一個測試用例的源代碼。

測試方法必須以單詞test開始,以便test runner能找到它們。在你的示例項目里,測試類包含了一個測試方法,叫做testExample。

 

setUptearDown方法就像守護在測試用例周圍的衛兵一樣。

把所有對象的程序設置代碼或重復性代碼放到setUp里,使測試用例方法保持清爽、高效。

類似的,關閉文件句柄或取消掛起網絡請求等清理活動的方法應該放到tearDown里。

 

Test runner 會依次調用setUp、testExample和tearDown方法。如果你申明了第二個測試方法testSecondExample,Test runner會依次調用setUp、testSecondExample,最后是tearDown方法。如果你有多個測試方法,setUp和tearDown會在一個測試環節調用多次——每經過一個測試用例方法調用一次!

 

這個故事的寓意是不要放任何處理太慢或處理頻繁的東西到setUp或tearDown方法里——這會讓你運行測試套件時面臨漫長的等待!

 

 

 

2.創建你的第一個測試

 

 

testExample方法只有一個叫做XCTFail的語句,正如它名字里暗示的:總是會失敗。這個語句不是非常有用,你可以寫一個比它更好的!刪除testExample方法,并添加如下方法:

- (void)test_addition_twoPlusTwo_isFour 
{  XCTAssert(
2 + 2 == 4, @"2 + 2 should be 4 but %d was returned instead", 2+2);}

測試用例的一個常用命名標準是:unitOfWork_stateUnderTest_expectedBehavior (工作單元_測試狀態_預期行為)。

在這個例子里,被測試的工作單元是加法,測試狀態是2 + 2,預期行為是結果為4。

所有XCTest斷言都有前綴XCT。XCTAssert是可用于單元測試的簡單斷言,第一個參數是預評估為ture的表達式,當斷言失敗時,其后NSLog風格的參數會顯示一條消息。

 

確保項目的當前target為iphone模擬器,通過窗口頂部目錄的PRoduct -> Test(Command-U)來運行測試,模擬器會啟動并執行測試套件。如果通知處于激活狀態,你會看到下列確認消息:

 

 

為了證實第一個單元測試成功,切換到Test Navigator,箭頭指出了它:

哈哈!翠綠色的小勾旁邊顯示出了你的單元測試。

你還可以看到邊框空白處菱形圖標旁的代碼,如下所示:

這些圖標展示關聯測試代碼的狀態:

@implementation旁的綠色小勾表示這個類測試通過,test_addition_twoPlusTwo_isFour旁的綠色小勾表示這個方法測試通過。

同時,這些圖標也是按鈕:

點擊@implementation旁的圖標將會運行這個類的所有測試,點擊其他測試方法旁的圖標則會運行該測試方法,試一試吧!

 

現在你已經對測試的概念和執行有了初步了解,是時候開始本章的示例項目了——測試開始!

 

二、開始項目

本章的剩余部分你將使用一個名為Reversi的黑白棋游戲項目,規則:兩個玩家,分別代表白方和黑方,輪流在8x8棋盤上落子。通過包圍對方棋子來吃掉它,游戲結束時棋子最多的為勝者。

如何創建這個游戲,請看:http://www.raywenderlich.com/29228/how-to-develop-an-ipad-board-game-app-part-12

下載本文頁尾提供的示例項目并運行,點擊屏幕下方的Vs Computer按鈕與電腦進行對戰,感受一下這個游戲的界面和玩法。

你獲勝了嗎?或者被AI對手爆出翔?不管怎樣,你的工作不是整日玩游戲——是時候添加一些有用的測試到項目里了。

 

1.添加測試的支持

第一個需要單元測試的是GameBoard類。這個類囊括了8x8棋盤的基本邏輯,64個單元格中的每個都有一個狀態——空、黑棋或白棋——并且GameBoard實例讓你能獲取并設置每一個方塊的狀態。 

打開GameBoard.h看一下里面的方法,在開始為現有代碼編寫測試之前,弄清楚各方法的作用和實現是一個好主意。

GameBoard.h,你會看到下列兩個方法:

// gets the state of the cell at the given location// raises an NSRangeException if the column or row are out of bounds- (BoardCellState) cellStateAtColumn:(NSInteger)column andRow:(NSInteger)row;// sets the state of the cell at the given location// raises an NSRangeException if the column or row are out of bounds- (void) setCellState:(BoardCellState)state forColumn:(NSInteger)column andRow:(NSInteger)row;

cellStateAtColumn:andRow: 和 setCellState:forColumn:andRow: 由你非常熟悉的getter/setter模式里發展出來,你的第一個測試是執行如下動作:

  • 初始化一個GameBoard實例
  • 設置cell狀態
  • 獲取cell狀態
  • 從指定的cell里獲取cell狀態

 

第一步是創建一個GameBoard測試類,右擊ReversiGameTests分組,選擇 iOS/Cocoa Touch/Objective-C test case class 創建一個名為GameBoardTests的測試類,繼承自XCTestCase。

確保你的新測試用例添加到ReversiGameTests target,如下圖(這個步驟非常重要,如果沒添加到正確的target里,你的測試不會運行):

 

打開 GameBoardTests.m 并且刪除 testExample 方法,你不需要它。

然后在 GameBoardTests.m 頂部導入頭文件(這僅僅是讓你的測試類能夠訪問GameBoard類):GameBoard.h 

#import "GameBoard.h"

 

你需要為你的所有測試提供一個GameBoard 實例,創建一個實例變量會比在每個測試里申明一個清爽得多。

GameBoardTests.m 里更新@interface 如下:

@interface GameBoardTests : XCTestCase 
{

  GameBoard *_board;}

現在你有了_board實例變量,可以開始測試了。

 

setUp 方法是第一次初始化_board的好地方,修改setUp如下:

- (void)setUp{  [super setUp];  _board = [[GameBoard alloc] init]; }

現在這個類的所有測試用例方法都能夠訪問初始化后的_board實例變量了。

 

2.第一個測試

這是你需要為首個測試用例添加的所有步驟,添加以下方法到GameBoardTests.m

- (void)test_setAndGetCellState_setValidCell_cellStateChanged {  [_board setCellState:BoardCellStateWhitePiece forColumn:4 andRow:5];
  BoardCellState retrievedState = [_board cellStateAtColumn:4 andRow:5];
  

  XCTAssertEqual(BoardCellStateWhitePiece,           retrievedState,           @"The cell should be white!");}

上面的代碼在(4,5)單元格里設置了一個白棋,并且立刻檢索了相同單元格的狀態。XCTAssertEqual 斷言檢查它們是否相等,如果不相等,你會看到一個異常信息,然后你將得知有一些東西需要檢查。

上面代碼的方法名遵循我之前提到的格式,通過這個方法名,你可以很容易看出它通過設置正確的單元格位置來測試setter和getter方法,并期待單元格狀態的改變。

 

如果你的測試工作是有計劃的,確保iPhone和iPad模擬器都測試,然后運行測試(Command-U)。

切換到Test Navigator,你會看到一個綠色小勾表示測試通過,如下圖:

這看起來只是一個簡單的測試,但是它在調試錯誤里提供了巨大的價值。

 

在內部, GAMEBOARD類使用一個簡單的二維數組來跟蹤8X8棋盤。但如果你曾經改變了代表向量或矩陣的數組,本次測試將作為回歸測試,確保interface 的基礎仍在工作。

作為一個附帶的好處,為現有的類編寫測試可以大大有助于理解代碼是如何工作的。分析類的方法可以幫助你辨別其功能,并為你編寫測試提供便利。

 

3.測試異常

按照設計的功能測試代碼有助于確保其正確性,但也使得你的app“早早失敗或高調失敗”——那些異常游戲狀態或無效條件被調試器很快抓住。

GameBoard.h里cellStateAtColumn:andRow: 和 setCellState:forColumn:andRow: 方法的注釋表明,如果行或列超出棋盤邊框,它們會彈出錯誤??雌饋砟阋呀浾业礁嗟臏y試條件。

添加下列兩個方法:

- (void)test_setCellState_withInvalidCoords_exceptionThrown {XCTAssertThrowsSpecificNamed([_board setCellState:BoardCellStateBlackPieceforColumn:10andRow:7], NSException,NSRangeException,@"Out-of-bounds board set should raise an exception");}- (void)test_getCellState_withInvalidCoords_exceptionThrown {XCTAssertThrowsSpecificNamed([_board cellStateAtColumn:7 andRow:-10],NSException,NSRangeException,@"Out-of-bounds board access should raise an exception");}

上面的代碼里,test_setCellState_withInvalidCoords_exceptionThrown: 試圖設置超出范圍的單元格(10,7),同時test_setCellState_withInvalidCoords_exceptionThrown: 試圖獲取超出范圍的單元格(7,-10)。再次的,方法名已指出在正測試不正確的坐標,報出異常正在意料之中。

 

XCTAssertThrowsSpecificNamed 采用以下四點作為參數:

  • 應該報出異常的表達式
  • 排除的類
  • 排除的名稱
  • 測試失敗時顯示的消息

點擊Command-U運行測試,你應該看到以下結果

這是什么?你希望用出色的代碼通過測試,但是兩個錯誤標記在Issue Navigator上。測試失敗信息也會顯示在代碼上,如下圖:

 

所有的測試失敗消息為:

[GameBoardTests test_getCellState_withInvalidCoords_exceptionThrown] failed: (([_board cellStateAtColumn:7 andRow:-10]) throws <NSException, "NSRangeException">) failed: throwing <NSException, "NSGenericException", "row or column out of bounds"> - Out-of- bounds board access should raise an exception

如果你分解上面的消息,你會看到你希望的行為是(throws <NSException, "NSRangeException">) ,而實際發生的是(throwing <NSException, "NSGenericException">) 。

在這個例子里,你期待的是NSRangeException ,但接收到的卻是NSGenericException 。

看起來你已經做了一些研究!

 

示例項目地址:http://pan.baidu.com/s/1o6x6zxg

 

 

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品久久久久久久久影视| 91精品久久久久久久久不口人| 影音先锋日韩有码| 日本韩国欧美精品大片卡二| 亚洲国产美女精品久久久久∴| 韩国三级电影久久久久久| 亚洲春色另类小说| 国产精品狼人色视频一区| 青青a在线精品免费观看| 成人伊人精品色xxxx视频| 在线丨暗呦小u女国产精品| 久久精品小视频| 久久精品国产欧美亚洲人人爽| 国产欧美日韩精品在线观看| 久久久久久久国产| 日韩精品一二三四区| 北条麻妃一区二区三区中文字幕| 成人深夜直播免费观看| 91久久久精品| 国产日韩欧美在线视频观看| 亚洲国产精品yw在线观看| 亚洲欧美在线免费观看| 国产婷婷97碰碰久久人人蜜臀| 国语自产精品视频在线看抢先版图片| 欧美黄色片免费观看| www.欧美三级电影.com| 欧美极品少妇全裸体| 中文字幕亚洲无线码a| 色琪琪综合男人的天堂aⅴ视频| 亚洲情综合五月天| 亚洲免费人成在线视频观看| 91沈先生作品| 国产免费一区二区三区香蕉精| 欧美老妇交乱视频| 精品毛片三在线观看| 亚洲娇小xxxx欧美娇小| 最近中文字幕mv在线一区二区三区四区| 亚洲成人激情在线| 色综合天天综合网国产成人网| 久久伊人精品视频| 欧美激情视频一区二区| 成人做爰www免费看视频网站| 91久久国产婷婷一区二区| 66m—66摸成人免费视频| 亚洲理论片在线观看| 国产精品r级在线| 国产精品免费视频xxxx| 亚洲精品欧美一区二区三区| 国产97免费视| 伊人成人开心激情综合网| 欧美性资源免费| 欧美人在线视频| 欧美色xxxx| 色999日韩欧美国产| 精品一区二区电影| 久久福利视频导航| 日韩精品亚洲精品| 亚洲综合一区二区不卡| 亚洲国产精品人人爽夜夜爽| 国产欧美韩国高清| 国产中文字幕91| 久久亚洲精品国产亚洲老地址| 国产在线精品一区免费香蕉| 欧美中文字幕在线观看| 91在线免费视频| 久久精品中文字幕免费mv| 日韩国产在线播放| 日韩精品视频免费在线观看| 国内精品久久久久久| 国产精品天天狠天天看| 日产日韩在线亚洲欧美| 国产精品揄拍500视频| 日韩久久精品成人| 成人h猎奇视频网站| 精品无人区乱码1区2区3区在线| 国产一区视频在线| 成人有码视频在线播放| 欧美日韩国产精品一区二区不卡中文| 国产精品av在线| 色yeye香蕉凹凸一区二区av| 国产成人免费av电影| 久国内精品在线| 欧美日韩在线一区| 97超碰蝌蚪网人人做人人爽| 97国产真实伦对白精彩视频8| 国产精品视频一| 久久国产精品偷| 亚洲va欧美va在线观看| 亚洲成人精品视频在线观看| 亚洲天堂第一页| 青青草原成人在线视频| 国产精品免费在线免费| 亚洲老头老太hd| 色青青草原桃花久久综合| 成人免费网站在线观看| 奇门遁甲1982国语版免费观看高清| 精品视频久久久久久| 国产在线98福利播放视频| 综合网日日天干夜夜久久| 亚洲精品视频久久| 日本一区二区在线播放| 在线看日韩av| 国内精品中文字幕| 亚洲三级 欧美三级| 国产日韩换脸av一区在线观看| 欧美一性一乱一交一视频| 91精品国产91久久久| 7777精品视频| 欧美高清自拍一区| 91美女福利视频高清| 国产精品久久久久久久久久久久久| 国产美女91呻吟求| 亚洲永久免费观看| 国内精品久久久久久久| 欧美人在线视频| 久久久久久久久久久国产| 91精品啪aⅴ在线观看国产| 国产成人综合精品在线| 欧美日韩精品国产| 亚洲日本成人女熟在线观看| 欧美激情一级精品国产| 国产精品精品视频| 91福利视频在线观看| 97不卡在线视频| 成人性生交大片免费看视频直播| 国产精品专区一| 美女av一区二区| 日韩欧美国产高清91| 欧美午夜宅男影院在线观看| 国产91精品黑色丝袜高跟鞋| 亚洲激情视频在线观看| 久久久久久一区二区三区| 国产成人自拍视频在线观看| 欧美性猛交丰臀xxxxx网站| 久久中文字幕在线视频| 日韩精品欧美激情| 国产精品专区一| 亚洲精品999| 国产精品99免视看9| 91久久精品国产| 久久99久久99精品中文字幕| 久久精品亚洲一区| 久久久久久高潮国产精品视| 在线观看久久av| 久久久国产精品x99av| 91成人在线视频| 亚洲福利视频网站| 成人黄色免费片| 中国日韩欧美久久久久久久久| 欧美在线激情网| 国语自产精品视频在线看抢先版图片| 亚洲一区二区三区香蕉| 亚洲美女又黄又爽在线观看| 精品久久久久久电影| 日韩精品中文字幕久久臀| 国产一区二区三区高清在线观看| 亚洲精品资源在线| 成人在线免费观看视视频| 中文字幕一区日韩电影| 亚洲一区二区福利| 久久97久久97精品免视看| 国产精品久久久久久中文字| 中文亚洲视频在线| 精品露脸国产偷人在视频|