單元測試,又稱模塊測試。是針對程序模塊(軟件設計的最小單位)來進行正確性檢驗的測試工做。面向過程編程,一個單元就是單個程序;面向對象編程,程序最小單位是方法。
html
XCTest是Xcode內置的測試框架。同時,Xcode6新增XCTestExpectation和性能測試。
算法
xcode6建立一個新的工程後,項目會自動配置兩個group:一個是「工程名稱」group;另外一個是「工程名稱Test」group。它們分別對應兩個target,一個是運行的target,另外一個是測試的target。用戶使用Command+R編譯運行的target,使用Command+U編譯測試的target。express
在測試的group中,有一個工程名稱test.m文件,這個文件裏面包含一個XCTestCase類,裏面有四個方法:setUp、tearDown、testExample、testPerformanceExample。編程
XCTestCasexcode
xcode的單元測試包含在XCTestCase的子類中,組織測試的時候儘可能須要考慮實際的應用操做流程。session
setUp & tearDownapp
setUp方法在XCTestCase的測試方法調用以前調用。當所有測試結束以後調用tearDown方法。框架
- (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; }
setUp方法能夠在測試以前建立一些 在test case中須要用到的一些對象等。tearDown方法則在所有的test case執行結束後清理測試現場,釋放資源、刪除不用的對象等。
異步
功能測試函數
test case中的每個方法都是以test開頭,這樣容易辨別。方法中會執行斷言Assert來判斷這個測試是否經過。
- (void)testExample { // This is an example of a functional test case. XCTAssert(YES, @"Pass"); }
經常使用的XCTest斷言
XCTest會用到不少斷言,這裏列舉一部分。
基本測試
全部的斷言都是從最基本的這個斷言演化出來的:
XCTAssert(expression,format……)
若是expression(表達式)執行結果爲true的話,這個測試經過;不然,測試失敗,並在控制檯輸出後面的format字符串。
Bool測試
對於bool型的數據,或者只是簡單的bool型表達式,使用XCTestAssertTrue或XCTestAssertFalse。
相等測試
測試兩個值是否相等使用XCTAssert[NO]Equal
XCTAssertEqual(expression1,expression2,format……)
在處理double、float類型數據的對比時使用XCTAssert[Not]EqualWithAccuracy來處理浮點精度的問題。
nil測試
使用XCTAssert[Not]Nil來判斷給定的表達式值是否爲nil。
無條件失敗斷言
使用XCTFail測試無條件斷言
XCTFail(format……)
XCTFail,無條件的都是測試失敗。這個東東有什麼用處呢?在測試裏面有這麼個狀況,咱們定義了測試方法,可是沒有給出具體的實現,那麼咱們確定不會但願這個測試能順利經過。是的,XCTFail就是這個用途。通常被用做一個佔位斷言,等咱們的測試方法完善好了以後在換成最貼近咱們測試的斷言。再或者,在某些狀況下else了以後就是不該該出現的狀況,那麼這個時候能夠將XCTFail放在這個else裏面。
性能測試
性能測試能夠幫助開發者創建一個主要功能的基本性能基線,確保這些主要功能代碼和算法能在這個性能基線內完成。
XCTestExpectation
XCTestExpectation是xcode自帶的異步測試類。即如今測試能夠等待指定長度的時間,一直到某些條件符合的時候再開始測試,而不用再寫不少的GCD代碼控制。
要使用異步測試,首先用方法expectationWithDescription建立一個expection。
let expectation = expectationWithDescription("……")
以後在方法的最後添加方法waitForExpectationsWithTimeOut,指定等待超時的時間和指定時間內條件沒法知足時執行的closure。
waitForExpectationsWithTimeOut(10) {(error) in ……}
接下來就是在異步測試剩下的回調函數中告訴expectation條件已經知足。
expectation.fulfill()
若是在測試中有多個expectation,則每一個expectation都必須fulfill,不然測試不經過。
func testAsynchronousURLConnection(){ let URL = NSURL(string: "http://www.baidu.com")! let expectation = expectationWithDescription("GET \(URL)") let session = NSURLSession.sharedSession() let task = session.dataTaskWithURL(URL, completionHandler: {(data, response, error) in expectation.fulfill() // 告訴expectation知足測試了 XCTAssertNotNil(data, "返回數據不該該爲空") XCTAssertNil(error, "error應該爲nil") if response != nil { var httpResponse: NSHTTPURLResponse = response as NSHTTPURLResponse XCTAssertEqual(httpResponse.URL!.absoluteString!, URL, "HTTPResponse的URL應該和請求URL一致") XCTAssertEqual(httpResponse.statusCode, 200, "HTTPResponse狀態碼應該是200") XCTAssertEqual(httpResponse.MIMEType as String, "text/html", "HTTPResponse內容應該是text/html") } else{ XCTFail("返回內容不是NSHTTPURLResponse類型") } }) task.resume() waitForExpectationsWithTimeout(task.originalRequest.timeoutInterval, handler: {error in task.cancel() }) }
總結
xcode內置工具已經很好了,即便很大的app也沒有必要爲了單元測試的代碼覆蓋率而排斥xcode內置工具。即不管怎麼樣的測試,XCTest的各類斷言、expectation和性能測試都足以應付。
若是在測試IOS或者OS X的APP,開始爲自動添加的測試類添加一些斷言並按下Command+U。咱們就會發現xocde自帶的工具讓咱們測試很方便。
斷言測試
測試方法的要求:1>必須無返回值;2>以test開頭
測試方法執行的順序:以方法名中test後面的字符大小有關,例如:
-(void)test001XXX會優於-(void)test002XXX執行
運行單元測試快捷鍵:Command+U
下面一共有18個斷言(SDK中也是18個)
XCTFail(format……)生成一個失敗的測試
XCTAssertNil(a1,format……)判空,a1爲空時經過,反之不經過。
XCTAssertNotNil(a1,format……)判不爲空,a1不爲空時經過,反之不經過
XCTAssert(expression,format……)當expression求值爲true時,測試經過。
XCTAssertTrue(expression,format……)當expression求值爲true時,測試經過
XCTAssertFalse(expression,format……)當expression求值爲False時,測試經過
XCTAssertEqual(a1,a2,format……)判斷相等,相等時測試經過
XCTAssertNotEqual(a1,a2,format……)判斷不等,不等時測試經過
XCTAssertEqualObjescts(a1,a2,format……)判斷相等,[a1 isEqual:a2]值爲True時經過,其中一個爲空時不經過。
XCTAssertNotEqualObjescts(a1,a2,format……)判斷不等,[a1 isEqual:a2]值爲False時經過
XCTAssertEqualWithAccuracy(a1,a2,accuracy,format……)判斷相等,(double或float類型)提供一個偏差範圍,在偏差範圍(+/-accuracy)之內相等時測試經過。
XCTAssertNotEqualWithAccuracy(a1,a2,accuracy,format……)判斷不等,(double或float類型)提供一個偏差範圍,在偏差範圍(+/-accuracy)之內不等時測試經過。
XCTAssertThrows(expression,format……)異常測試,當expression發生異常時經過,反之不經過
XCTAssertNotThrows(expression,format……)異常測試,當expression沒有發生異常時經過,反之不經過
XCTAssertThrowsSpecific(expression, specificException, format...) 異常測試,當expression發生specificException異常時經過;反之發生其餘異常或不發生異常均不經過
XCTAssertNoThrowSpecific(expression, specificException, format...)異常測試,當expression沒有發生具體異常、具體異常名稱的異常時經過測試,反之不經過
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)異常測試,當expression發生具體異常、具體異常名稱的異常時經過測試,反之不經過
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)異常測試,當expression沒有發生具體異常、具體異常名稱的異常時經過測試,反之不經過
舉例子應用
//1.比較基本數據類型
XCTAssertEqual(1,2,@"a1 = a2 shoud be true");//測試沒經過
XCTAssertEqual(1,1,@"a1 = a2 shoud be true");//測試經過
//2.若是a1,a2是指針,則當他們指向同一個對象時纔會返回YES,以下:
NSArray *array1 = @[@1];
NSArray *array2 = @[@1];
NSArray *array3 = array1;
XCTAssertEqual(array1,array2,@"a1 and a2 shoulid point to the same object");//測試不經過
XCTAssertEqual(array1,array3,@"a1 and a2 shoulid point to the same object");//測試經過
//3.要注意使用NSString
NSString *str1 = @"1";
NSString *str2 = @"2";
NSString *str3 = str1;
XCTAssertEqual(str1,str2,@"a1 and a2 shoulid point to the same object");//測試經過
XCTAssertEqual(str1,str3,@"a1 and a2 shoulid point to the same object");//測試經過
儘管str1與str2指向不一樣的對象,可是兩者的指針比較依然經過了測試。因爲str1與str2指向同一個常量,常量在data段中地址是固定的,因此兩者地址相同。