iOS --- 使用XCTest進行單元測試

來源:互聯網
上載者:User

iOS --- 使用XCTest進行單元測試

測試驅動開發(TDD)是當前流行的開發理念,XCTest是Apple封裝的單元測試類庫。使用XCTest進行單元測試的流程比較簡單,本部落格僅簡單介紹下XCTest的使用。但對於單元測試的理解(何時使用,如何更高效地驅動開發)卻是一個需要積累的過程,要在TDD的過程中仔細體會。

setUp和tearDown

一個測試案例以一個Objective-C類的形式存在,其implementation中有預設的setUp和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。

最左邊有個小表徵圖,點擊之後即可執行該測試case。

效能測試

效能測試可直接使用 - (void)measureBlock:(void (^)(void))block; 進行,傳遞參數即為要執行工作群組成的一個block。
如以下的case可用於測試measureBlock接收的block參數中執行的效能。

Baseline即可設定該效能是否合格的參考基準。
注意,一個效能測試case中只能執行一次measureBlock,即只能測試一個指定block步驟的效能(這其實也是合乎情理的,混到一塊了哪裡還能區分出效能測試的結果)。因此,在while,for等迴圈中是不能使用measureBlock的,否則會出錯。
measureMetrics的用法跟measureBlock類似。
當然,也可以使用startMeasuring和stopMeasuring方法進行效能測試,但絕大多數情況下使用measureBlock已經足夠了。

效能測試的宏定義

例如,在單獨測試一個圖片濾鏡的效能時,可以這樣:

- (void)testPerformanceFilter1 {    [self measureBlock:^{        NSInteger filterid = 100;        UIImage *filteredImage = [FilterTool filterImage:self.image withFilterId:filterid];        XCTAssertNotNil(filteredImage, @"濾鏡應該非空");    }];}

那麼,如果有幾十個濾鏡需要進行效能測試呢?
因為單元測試case的方法名不能傳遞參數,且迴圈中不能使用measureBlock,因此對於大量重複的效能測試case,目前看來採用宏定義是比較好的解決方案。

#define TestFilterPerformance(filterid) - (void)testFilterPerformance_##filterid { \    [self measureBlock:^{ \        UIImage *filteredImage = [FilterTool filterImage:self.image withFilterId:filterid]; \        XCTAssertNotNil(filteredImage, @"濾鏡應該非空"); \    }]; \}

則使用起來,就可如下定義所有的測試case了。

非同步測試

XCTest提供了XCTestExpectation來進行非同步測試,即可在指定時機使用其fulfill執行個體方法開始執行斷言命令。例如以下是一個完整的網路請求的測試範例,可用於測試server端是否正常,要在對應的block中進行斷言。

- (void)testAsynchronousURLConnection {    XCTestExpectation *expectation = [self expectationWithDescription:@"GET Baidu"];    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/"];    NSURLSession *session = [NSURLSession sharedSession];    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        // XCTestExpectation條件已滿足,接下來的測試可以執行了。        [expectation fulfill];        XCTAssertNotNil(data, @"返回資料不應非nil");        XCTAssertNil(error, @"error應該為nil");        if (nil != response) {            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;            XCTAssertEqual(httpResponse.statusCode, 200, @"HTTPResponse的狀態代碼應該是200");            XCTAssertEqual(httpResponse.URL.absoluteString, url.absoluteString, @"HTTPResponse的URL應該與請求的URL一致");        } else {            XCTFail(@"返回內容不是NSHTTPURLResponse類型");        }    }];    [task resume];    // 逾時後執行    [self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) {        [task cancel];    }];}

即:非同步網路請求操作正常執行,但斷言命令僅在[expectation fulfill];結束後才開始執行,這樣能確保得到網路請求的返回結果後執行相應斷言。同時,可設定逾時時間及對應操作。
否則,就需要使用定時機制等處理類似情況。

訪問待測類的私人變數

在case中,如何訪問一個待測類的私人變數呢?對該類進行相應的擴充即可。

#import #import "FilterTool.h"@interface FilterTool (UnitTest)@property (strong, nonatomic) FilterController *filterController;- (void)didSelectFilterCellAtIndexPath:(NSIndexPath *)indexPath;@end@interface FilterToolTest : XCTestCase@end@implementation FilterToolTestXXXX@end

FilterTool類的filterController屬性和didSelectFilterCellAtIndexPath:方法本是私人的,若想對其進行測試,則必須將其加入擴充。

斷言命令
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語言標量、結構體或聯合體時使用,實際測試發現NSString也可以);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沒有發生具體異常、具體異常名稱的異常時通過測試,反之不通過.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.