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

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

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

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

4.測試失敗的調試

是時候追蹤之前測試失敗的問題了。打開GameBoard.m,找到cellStateAtColumn:andRow: 和 setCellState:forColumn:andRow: 方法,你會看到它們都調用了一個叫做checkBoundsForColumn:andRow: 的helper方法,用來檢測數組邊界。

頭文件 GameBoard.h 里的方法注釋如下:

// raises an NSRangeException if the column or row are out of bounds

然而,如果超出邊界,checkBoundsForColumn:andRow: 方法的實現拋出了一個NSGenericExPRession 。通常的,你把頭文件里的注釋當做一個公共API規范,但在這個例子里代碼和規范并不匹配,你該如何做?

 一個可能性是更新注釋和相關的測試,以匹配當前的實現。在這個例子里,規范里的注釋看起來更有意義:一個邊界檢查應當遵循NSArray,并升起一個NSRangeException

 

在GameBoard.m里,更新checkBoundsForColumn:andRow: 方法的實現如下:

- (void)checkBoundsForColumn:(NSInteger)column andRow:(NSInteger)row{if (column < 0 || column > 7 || row < 0 || row > 7)[NSException raise:NSRangeExceptionformat:@"row or column out of bounds"];}

重新運行測試,這時所有測試應該能夠通過了。

自從代碼不同步,注釋里的規范總是有一點危險。然而,你的測試可以為注釋添加雙保險。自從你編寫測試代碼后,只要你經常運行測試,這些實現不匹配的風險會大大減??!

另外,你的測試提供了一個偉大的高層概覽代碼,特別是遵循建議的命名規范以后。當你重新進入很久沒碰過的代碼后,這會非常方便——正如下一小節的內容。

 

5.保證測試bug

一個崩潰報告剛剛進入你的app:你的一個測試人員報告你,當她運行

你自己試一遍,就會在控制臺看到下列信息:

崩潰看起來重復發生,是什么拋出了一個NSRangeException ?call stack提供了以下信息:

2 CoreFoundation +[NSException raise:format:] + 1393 ReversiGame -[GameBoard checkBoundsForColumn:andRow:] + 142 4 ReversiGame -[GameBoard cellStateAtColumn:andRow:] + 765 ReversiGame -[ReversiBoard flipOpponentCountersForColumn: andRow:withNavigationFunction:toState:] + 2816 ReversiGame -[ReversiBoard makeMoveToColumn:andRow:] + 245 7 ReversiGame -[BoardSquare cellTapped:] + 192

從下往上讀:

第7、6行  tap觸發代碼用來處理玩家的移動

第5行 游戲邏輯檢查是否有對手的棋子被包圍并且翻轉

第4、3行 代碼然后調用cellStateAtColumn:andRow: 和

checkBoundsForColumn:andRow:

第2行 底層框架報出一個越界異常

 

想了解更多調試崩潰的信息?看這里

My App Crashed, Now What?http://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1Demystifying iOS application Crash Logshttp://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs

這是一個測試這些崩潰條件的絕好機會。

你的新測試不止要修復這個問題,而且要作為一個回歸測試確保這個bug保持修復。沒有什么比修復一個bug后,數月之后添加新功能或重構代碼時再遇到相同的bug更讓人不爽的了。

 

6.決定什么需要測試

你知道你需要測試——但應該測試什么?

ReversiBoard 是GameBoard類的通用實現,所以從這里開始故障排除工作是有意義的。

 

使用iOS/Cocoa Touch/Objective-C test case class 模板創建一個新類,命名為ReversiBoardTests, 繼承自XCtestCase。

在開始之前,刪除模板文件的testExample方法,然后在ReversiBoardsTests.m 里導入頭文件:

#import "ReversiBoard.h"

 

ReversiBoardsTests.m 里改變@interface 如下:

@interface ReversiBoardTests : XCTestCase { ReversiBoard *_reversiBoard;}

添加一個_reversiBoard 實例變量意味著你不用在每個測試方法里反復實例化。

然后修改setUp方法如下:

- (void)setUp {[super setUp];_reversiBoard = [[ReversiBoard alloc] init];}

 

7.測試否定

在之前的編寫的測試中,異常的存在是預期的結果。這一次,異常并沒有在你的測試基礎上出現。

添加這些方法到ReversiBoardsTests.m 

?- (void)test_makeMove_inPreGameState_nothingHappens {[_reversiBoard setToPreGameState];XCTAssertNoThrowSpecificNamed([_reversiBoard makeMoveToColumn:3 andRow:3],NSException,NSRangeException,@"Making a move in the pre-game state should do nothing");}

上面的代碼中,測試設置游戲前的狀態。也就是說,玩家作出對戰AI還是對戰其他玩家選擇之前的狀態。這個測試模擬了一進入游戲就點擊棋盤的動作。

XCTAssertNoThrowSpecificNamed 斷言與XCTAssertThrowsSpecificNamed 剛好相反。如果指定的異常被拋出,上面的測試會失??;如果指定的異常沒被拋出,測試會通過。

你還沒有修復bug,所以現在運行代碼將會失敗——不過這是件好事,在修復bug之前編寫測試意味著你擁有重現bug的測試能力。

 

Command+U 運行測試,你會看到如下信息:

test failure: -[ReversiBoardTests test_makeMove_inPreGameState_nothingHappens] failed: (([_reversiBoard makeMoveToColumn:3 andRow:3]) does not throw <NSException, "NSRangeException">) failed

 

8.校正代碼

打開 ReversiBoard.m 然后找到 makeMoveToColumn:andRow: 方法。

思考一下如何修正這個特定的bug。只有用戶選擇了游戲模式之后才可以移動,這是很有意義的。這樣一想,游戲前和游戲后的游戲邏輯沒有什么不同。

幸運的是,這里有一個屬性指定當前的游戲狀態:gameState.

 

添加以下代碼到makeMoveToColumn:andRow: 方法的頂部:

if ([self gameState] != GameStateOn) return;

這個條件檢測了當前的游戲狀態。如果狀態不是GameStateOn——說明游戲不在運行中——方法立即終止。

運行app,測試一下在選擇游戲模式之前點擊棋盤,是否崩潰?

 

最后,Command+U 運行測試,Test Navigator應該顯示綠色小勾,bug被碾碎了!

探索風格的測試只用包含明顯問題的代碼,然而回歸風格的測試則可以為經常修復某個問題提供了保障。

修復每個bug不止是讓你的代碼更健康,同時讓你有更多時間思考你的單元測試。

 

 

三、下一步何去何從?

測試是開發生涯的一個巨大任務,這章我們掌握了單元測試的基礎,下面是一些有益的概念:

  • 使用哪一個斷言?在哪里使用斷言?
  • 添加測試到一個現有app
  • 在程序說明里使用測試
  • 探尋并修復bug
  • 確保已經修復過的bug不再出現

 

Xcode中整合的XCTest讓建立測試套件非常容易,整個iOS領域的測試范圍是非常廣大的,更多測試概念:

  • Mock objects
    • 在測試里模擬出足夠真實的對象
      • http://ocmock.org/
  • UI testing
    • 可以模擬出用戶的輸入,比如touch或文本輸入。
  • Continuous integration (CI) systems
    • 將會自動運行單元測試,想了解更多關于CI的功能,閱讀本書14、15章“Beginning and Intermediate Continuous Integration in Xcode 5  

 

在深度學習測試之前,這里有幾個挑戰來讓你掌握本章的概念。

 

四、挑戰

GameBoard 類仍然還有一些方法沒被測試——你的任務是編寫測試,為你的app提供一個完整的測試套件。

 

1.挑戰一:測試 clearBoard

clearBoard 清除棋盤上的所有棋子。自從已經測試getter和setter 方法后,你可以假設這些方法無需再次測試。

celarBoard的測試用例有以下幾個步驟:

1)至少設置一個黑棋在棋盤上

2)至少設置一個白棋在棋盤上

3)調用clearBoard

4)檢查你現在放置白棋和黑棋的地方是空的(提示:狀態為BoardCellStateEmpty)

記住測試用例遵循的命名格式:工作單元或方法名、測試什么、預期的結果

 

2.挑戰二:測試scorekeeper

countCellsWithState: 記錄棋盤上特定狀態棋子的數量。這個方法計算出最后的分數,所以確保它正確工作是非常必要的! 

countCellsWithState: 的測試用例將執行以下動作:

1)設置一些黑棋或白棋在棋盤上

2)追蹤棋子增加的數量

3)比較你的數量與countCellsWithState:返回的數量

countCellsWithState:有一個狀態參數,所以它看起來像這樣

[_board countCellsWithState:BoardCellStateWhitePiece]

再次,確定你的測試用例命名恰當

祝你測試成功!

 

附錄:XCTest斷言參考

下列所有斷言都使用(format...)作為最后一個參數,這個NSlog風格的參數會在測試失敗時顯示消息。

XCTFail(format...)無條件失敗;用來標記不應執行的代碼部分XCTAssertNil(exp, format...)XCTAssertNotNil(exp, format...)表達式應為nil或not nil;在OC對象中使用 XCTAssert(exp, format...)XCTAssertTrue(exp, format...)XCTAssertFalse(exp, format...)表達式應為true或false XCTAssertEqualObjects(a1, a2, format...)OC對象a1和a2應該相等;使用isEqual: 來保持相等 XCTAssertEqual(a1, a2, format...)參數a1和a2應該相等;用來比較C數量、集合及結構體(如CGRect和CGPoint);使用NSValue來比較 XCTAssertEqualWithAccuracy(a1, a2, delta, format...)參數a1與參數a2應該與給定的delta值相等;使用float和double類型,其中小數值可能不夠精確 XCTAssertThrows(exp, format...)XCTAssertThrowsSpecific(exp, exception, format...)XCTAssertThrowsSpecificNamed(exp,exception,exceptionName,format...)表達式應該拋出一個異常信息;更詳細的版本讓你指出類名和異常名 XCTAssertNoThrowXCTAssertNoThrowSpecificXCTAssertNoThrowSpecificNamed如果異常被拋出,這些斷言會失敗

 

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲成人a**站| 91精品久久久久久久久久入口| 欧美专区国产专区| 91人成网站www| 国产一区在线播放| 国产福利视频一区| 国产日韩欧美电影在线观看| 青青草原一区二区| 色妞在线综合亚洲欧美| 在线播放日韩专区| 91日本视频在线| 日韩在线资源网| 欧美日韩成人免费| 亚洲精品电影网站| 日韩大片免费观看视频播放| 91精品中文在线| 亚洲第一精品夜夜躁人人爽| 色婷婷综合久久久久中文字幕1| 久久精品成人欧美大片古装| 日韩国产精品亚洲а∨天堂免| 日日狠狠久久偷偷四色综合免费| 九九热r在线视频精品| 日韩中文字幕在线精品| 国产91精品久久久久久久| 日韩欧美精品网站| 欧美极品欧美精品欧美视频| 美女国内精品自产拍在线播放| 一区二区欧美日韩视频| 日韩视频在线一区| 国外成人免费在线播放| 欧美精品福利视频| 亚洲国产高清高潮精品美女| 51色欧美片视频在线观看| 久久精品国产亚洲精品2020| 国产精品高清免费在线观看| 神马久久久久久| 成人免费淫片视频软件| 亚洲视频在线观看免费| 久久久久久久久国产精品| 国产成人精品一区二区在线| 国产日本欧美在线观看| 国产亚洲欧美日韩精品| 在线视频一区二区| 欧美又大又硬又粗bbbbb| 国产欧美一区二区三区久久人妖| 97视频在线观看免费| 成人激情电影一区二区| 亚洲一区二区三区在线免费观看| 在线成人激情黄色| 日本高清不卡在线| 亚洲综合小说区| 91黑丝在线观看| 亚洲男人的天堂在线播放| 最近日韩中文字幕中文| 北条麻妃久久精品| 欧美日韩免费区域视频在线观看| 日韩成人在线电影网| 成人av在线网址| 精品国产91乱高清在线观看| 国内免费久久久久久久久久久| 中文字幕亚洲欧美在线| 91亚洲精品久久久久久久久久久久| 九九久久国产精品| 欧美日韩国产在线播放| 中文字幕日韩综合av| 色先锋资源久久综合5566| 夜夜嗨av色一区二区不卡| 久久久久久久久久久网站| 欧美日本高清视频| 国产成人精品一区二区| 91久久久久久久久| 国产欧美一区二区三区四区| 日韩欧美中文第一页| 日本精品一区二区三区在线播放视频| 欧美性受xxxx黑人猛交| 亚洲国产精品免费| 欧美激情免费视频| 国产精品三级美女白浆呻吟| x99av成人免费| 亚洲午夜色婷婷在线| 亚洲xxxx做受欧美| 国产精品久久久久久久美男| 欧美一区二粉嫩精品国产一线天| 亚洲成人久久久| 国产91九色视频| 欧美日韩在线视频一区| 国产精品免费一区二区三区都可以| 最新国产精品拍自在线播放| 91视频国产高清| 日韩精品在线电影| 亚洲精品乱码久久久久久金桔影视| 91夜夜揉人人捏人人添红杏| 亚洲专区在线视频| 一区二区三区 在线观看视| 国模吧一区二区| 精品一区二区三区电影| 亚洲第一网站免费视频| 久热99视频在线观看| 国产精彩精品视频| 中文字幕日韩在线播放| 懂色av影视一区二区三区| 性欧美亚洲xxxx乳在线观看| 日韩精品中文字| 日韩欧美成人区| 久久久亚洲天堂| 日韩午夜在线视频| 国产精品1234| 色偷偷91综合久久噜噜| 欧洲成人午夜免费大片| 69久久夜色精品国产69| 日韩精品极品视频| 久久综合88中文色鬼| 国产精品久久久久免费a∨| 91在线|亚洲| 日韩精品免费在线视频观看| 国产一区二区三区中文| 欧美激情一区二区三区久久久| 日韩中文有码在线视频| 久久久久久久久久久亚洲| 欧美激情精品久久久久久大尺度| 精品久久久久久亚洲精品| 一本色道久久88综合日韩精品| 国产亚洲精品91在线| 日本一区二区不卡| 一区二区在线免费视频| 亚洲欧美日韩国产中文| 精品国产乱码久久久久久婷婷| 国产亚洲欧洲高清| 亚洲精品不卡在线| 国产这里只有精品| 亚洲黄页视频免费观看| 国产精品久久二区| 国产va免费精品高清在线观看| 亚洲精品美女免费| 国产一区二区三区在线播放免费观看| xvideos亚洲人网站| 久久久电影免费观看完整版| 久久精品久久久久| 91久久久久久久久久久| 国产在线98福利播放视频| 久久久在线视频| 精品香蕉一区二区三区| 狠狠久久五月精品中文字幕| 亚洲欧洲中文天堂| 日韩精品在线免费观看视频| 成人黄色av播放免费| 国产99久久精品一区二区永久免费| 欧美日韩国产麻豆| 日韩成人免费视频| 91精品在线播放| 国产精品久久久久久搜索| 日本午夜在线亚洲.国产| 91在线看www| 国产美女扒开尿口久久久| 国产精品麻豆va在线播放| 国产成人97精品免费看片| 日韩在线观看免费高清| 国产亚洲成av人片在线观看桃| 欧美精品午夜视频| 日韩中文字幕在线看| 日本精品视频在线观看| 久热99视频在线观看| 一区二区三区回区在观看免费视频| 国产亚洲精品综合一区91|