Xcode 自帶單元測試

weixin_33830216發表於2018-06-27

使用背景

1.為了更快、更高效的開發, 開發過程中經常要寫一些測試用例。 2.在開發過程中,有些很深的介面,需要滿足很多條件、造很多假資料才可以進入的,但是前面那些介面我們根本就沒有涉及修改,只是想進入最後這個介面;比如:訂單支付完成介面。 這時候我們可以寫測試用例,直接讓其進入到想要進入的介面。

測試用例分為:單元測試和UI測試。 Xcode自帶了測試用例檔案。一般大的專案以及優秀的開源庫都有測試用例的,比如:AFNetworking。 不會寫的可以到這下載AFNetworking原始碼參考。

建立測試用例

1.新建工程檔案,勾選測試用例

如果忘記勾選了, 也可以通過新建來建立。 和新建檔案一樣。

2.新建完的工程 測試用例和其他工程檔案,分別屬於不同的target。

3.測試用例檔案 新的的測試用例檔案,都是這個結構和基本的四個方法。

#import <XCTest/XCTest.h>

@interface XcodeTestsTests : XCTestCase

@end

@implementation XcodeTestsTests

/*!
 *  @brief 初始化方法。
 *  初始化、程式碼複用、準備測試條件
 */
- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}
/*!
 *  @brief 銷燬方法
 *  每次測試用例跑完,都會跑這個方法,釋放物件、回收資源、避免干擾
 */
- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}
/*!
 *  @brief 測試用例方法
 *  注意: 這裡方法必須以test開頭,不然識別不了。
 *  開始測試用例方法,cmd+u  或者直接點選右側這個小框箭頭即可
 */
- (void)testExample {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
}

/*!
 *  @brief 效能測試方法
 *  可以測試某一段方法的效能、耗時情況
 */
- (void)testPerformanceExample {
    // This is an example of a performance test case.
    [self measureBlock:^{
        // Put the code you want to measure the time of here.
    }];
}

@end
複製程式碼

寫測試用例基本都在testExample方法裡完成。

注意:問題點

寫了一個最簡單的測試用例,執行不起來, 執行報錯:-[UIApplication applicationState] must be used from main thread only。控制檯報錯資訊:Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]

解決辦法: 開啟Xcode的Edit Scheme, 找到Test選項,去掉Runtime Api 檢測選項即可。

以上正常情況下就可以執行了。 下面我們開始寫一個簡答的測試用例。

寫測試用例

測試用例的過程一般分三步,這裡以測試ViewController的一個加方法為例:

  1. 在VC裡暴露介面:
/*!
 *  @brief 暴露介面
 *  暴露介面這裡很重要,很有技術含量。
 *  儘可能的暴露少的資訊來完成測試用例
 */
- (NSInteger)addFunction:(NSInteger)a andB:(NSInteger)b;
複製程式碼

然後實現方法:

- (NSInteger)addFunction:(NSInteger)a andB:(NSInteger)b {
    return a + b;
}

複製程式碼

2.在測試用例裡匯入標頭檔案#import "ViewController.h" 以及初始化物件,準備測試條件。

3.開始測試方法

- (void)testAddFunction {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
    //1.建立測試條件
    NSInteger a = 1, b = 2;
    //2.進行測試,直接呼叫測試方法
    NSInteger sam = [self.VC addFunction:a andB:b];
    
    //3.斷言。斷言方法有N多種,詳細見下面。  測試最核心。
    XCTAssertEqual(sam, 3);  //前面這個是測試條件,後面的值是我們期望的值。 如果是正確的就測試通過,否則直接掛掉。
    
}
複製程式碼

斷言一覽表:

 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時通過;
XCTAssertEqualObjects(a1, a2, format...)判斷相等,[a1 isEqual:a2]值為TRUE時通過,其中一個不為空時,不通過;
XCTAssertNotEqualObjects(a1, a2, format...)判斷不等,[a1 isEqual:a2]值為False時通過;
XCTAssertEqual(a1, a2, format...)判斷相等(當a1和a2是 C語言標量、結構體或聯合體時使用, 判斷的是變數的地址,如果地址相同則返回TRUE,否則返回NO);
XCTAssertNotEqual(a1, a2, format...)判斷不等(當a1和a2是 C語言標量、結構體或聯合體時使用);
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判斷相等,(double或float型別)提供一個誤差範圍,當在誤差範圍(+/-accuracy)以內相等時通過測試;
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判斷不等,(double或float型別)提供一個誤差範圍,當在誤差範圍以內不等時通過測試;
XCTAssertThrows(expression, format...)異常測試,當expression發生異常時通過;反之不通過;(很變態) XCTAssertThrowsSpecific(expression, specificException, format...) 異常測試,當expression發生specificException異常時通過;反之發生其他異常或不發生異常均不通過;
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)異常測試,當expression發生具體異常、具體異常名稱的異常時通過測試,反之不通過;
XCTAssertNoThrow(expression, format…)異常測試,當expression沒有發生異常時通過測試;
XCTAssertNoThrowSpecific(expression, specificException, format...)異常測試,當expression沒有發生具體異常、具體異常名稱的異常時通過測試,反之不通過;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)異常測試,當expression沒有發生具體異常、具體異常名稱的異常時通過測試,反之不通過
複製程式碼

非同步測試

舉一個最簡答的例子:進入到具體介面裡的的方法:

    //這裡就直接定義一個字串,假如出現異常,就直接丟擲這個字串
	XCTestExpectation *ex = [self expectationWithDescription:@"這裡應該得進到訂單完成介面"];
	OrderPayDoneViewController *controller = [[OrderPayDoneViewController alloc] initWithNibName:nil
																								bundle:nil];
    //這裡就是訂單完成介面需要的屬性,可以隨便造假資料
	controller.orderId = @"這是訂單 ID";
	controller.isPaidSuccess = YES;
	controller.orderAmount = @"23456";
	controller.payMethod = @"Paypal";
	controller.displayAmount = @"$11.8.0";
	[CurrentViewController().navigationController pushViewController:controller
															   animated:YES];
//下面這兩個方法就是XCTestExpectation的API
	[ex fulfill];  //這個方法不懂, 不寫也可以呼叫
	[self waitForExpectations:@[ex] timeout:1000000];//這個不呼叫不能跳轉
複製程式碼

單元測試

單元測試內容很多,還需要更多的研究,測試也很重要,對於開發對於測試都很重要,多多學習下單元測試吧。

後續

UI測試,可以自動進行測試。最基本的註冊登入流程等常規,可以跑UI測試。。 內容比較多, 後續繼續研究補充。

相關文章