1. 程式人生 > >iOS 單元測試

iOS 單元測試

輸入文本 描述 expec 分配內存 一個 按鈕 http請求 響應 執行順序

一、前言:

UITest的單元測試能最大限度的解放測試妹妹的雙手,當然也會給程序員帶來巨大工作量,完整的測試代碼估計是項目代碼的兩倍,另外大家可以自行百度 Xcode Coverage 查看測試代碼覆蓋率,這篇文章只講如何在工程中用XCTest框架做單元測試。
其中主要介紹了,用六個按鈕示意的UITests使用和性能測試、異步測試的。
二、創建工程:

先創建個名字為 XCTest 的示例工程:
這裏寫圖片描述
這裏要說明一下如果當初創建工程時未勾選上Include Unit Tests 和 Include UI Test 這兩個復選框,可在項目工程根目錄下手動創建 Tests 、UITests文件夾,如下圖示例:
這裏寫圖片描述
這裏的”XC”是工程名字,XCTests,UITests這兩個文件夾下的Info.plist 是一模一樣的,裏面包含的 key value 和app裏的 Info.plist 是一樣的,即:
這裏寫圖片描述
這裏寫圖片描述
三、代碼解釋:

1、接下來看看具體代碼:
我們可以在 XCTests.m XCUITests.m 中發現一些共同的方法:

- (void)setUp { … }

1

- (void)tearDown { … }

1

2、方法的意義:
將要開始執行測試代碼時調用: - (void)setUp { … } ,
測試代碼執行完後調用,測試失敗不調用: - (void)tearDown { … },
其他任何方法都會在 - (void)setUp 和 - (void)tearDown 調用。
所有的測試類類名都以Tests結尾,同樣類中所有的測試方法也都以- (void)test 開頭。

3、獲取app啟動對象:

[[[XCUIApplication alloc] init] launch];///為app對象分配內存並啟動它

1

4、其他:
UI測試示例代碼:

XCUIElement *button1 = [[XCUIApplication alloc] init].buttons[@"1111"];///獲取名字為2222的按鈕
XCTAssertTrue(button1.exists, @"‘1111‘按鈕存在");///#值為true才能通過,為false會停在這裏
[button1 tap];///觸發按鈕的點擊事件

1
2
3

性能測試示例代碼:

NSLog(@"性能測試");
[self measureBlock:^{ ///#用來分析代碼執行的時間,log會打印在 console 裏,同時本地也會有一份日誌
//實例化測試對象
///#測試那個類裏的方法就要引入那個類
ViewController *vc = [[ViewController alloc] init];
//#調用測試方法獲取測試結果
[vc performanceExample];
}];


1
2
3
4
5
6
7
8
9
10

異步測試示例代碼:
註意其中的“執行順序1、2、3、4”

北京整形醫院http://www.shkqmrw.com/
北京整形醫院http://www.scytsa.com/

XCTestExpectation *expectation = [self expectationWithDescription:@"百度翻譯 測試"];
NSLog(@"執行順序:1");
///請求參數
NSMutableDictionary *paramer = [NSMutableDictionary dictionary];
[paramer setValue:@"apple" forKey:@"q"];
[paramer setValue:@"en" forKey:@"from"];
[paramer setValue:@"zh" forKey:@"to"];
[paramer setValue:@"2015063000000001" forKey:@"appid"];
[paramer setValue:@"1435660288" forKey:@"salt"];
[paramer setValue:@"f89f9594663708c1605f3d736d01d2d4" forKey:@"sign"];
///開始請求
[ViewController networkRequestWithAPI:@"https://api.fanyi.baidu.com/api/trans/vip/translate" requestMethod:@"POST" cachePolicy:NSURLRequestUseProtocolCachePolicy requestParamer:paramer Completion:^(NSDictionary * _Nullable result, NSURLResponse * _Nullable response, NSError * _Nullable error) {

[expectation fulfill];///調用fulfill後 waitForExpectationsWithTimeout 會結束等待
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
XCTAssertTrue(httpResponse.statusCode==200, @"接口請求成功");///200表明http請求成功,請求失敗會停在這裏
XCTAssertNotNil(result, @"json 對象不為空");///result結果為nil,會停在這裏
XCTAssertNil(error, @"請求沒有出錯");//error 不為nil,會停在這裏
NSLog(@"執行順序:3");
}];
NSLog(@"執行順序:2");
///因為接口設置的是30秒超時,所以這裏也設置30秒,意思就是這個線程最多等待30秒,
[self waitForExpectationsWithTimeout:30.f handler:^(NSError * _Nullable error) {
NSLog(@"執行順序:4");
if (error) {
///測試代碼無異常
} else {
///測試代碼有異常
}
}];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述
四、圖標解釋:

1、測試前的圖標:
這裏寫圖片描述 這個圖標出現在所有以 - (void)test 開頭的方法前,這個是將要開始測試前的按鈕狀態圖標,一旦點擊就開始測試這個方法裏的內容,或者我們也可以通過 command+U 的快捷鍵啟動完整測試,完整測試會執行 Tests 和 UITests 下所有的測試類和類中所有的測試方法。

2、測試成功圖標:
這裏寫圖片描述
綠色代表測試成功,同時xcode 也會彈框提示,
這裏寫圖片描述

3、測試失敗:
這裏寫圖片描述
表示某個測試方法測試失敗,同時進程也會停在測試未通過的代碼那。
這裏寫圖片描述
五、斷言註釋:

XCTFail(format…) //生成一個失敗的測試;
XCTFail(@”Fail”);

XCTAssertNil(a1, format…) //為空判斷, a1 為空時通過,反之不通過;
XCTAssertNil(@”not nil string”, @”string must be nil”);

XCTAssertNotNil(a1, format…) //不為空判斷,a1不為空時通過,反之不通過;
XCTAssertNotNil(@”not nil string”, @”string can not be nil”);

XCTAssert(expression, format…) //當expression求值為TRUE時通過;
XCTAssert((2 > 2), @”expression must be true”);

XCTAssertTrue(expression, format…) //當expression求值為TRUE時通過;
XCTAssertTrue(1, @”Can not be zero”);

XCTAssertFalse(expression, format…) //當expression求值為False時通過;
XCTAssertFalse((2 < 2), @”expression must be false”);

XCTAssertEqualObjects(a1, a2, format…) //判斷相等, [a1 isEqual:a2] 值為TRUE時通過,其中一個不為空時,不通過;
XCTAssertEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return YES”);
XCTAssertEqualObjects(@”1″, @”2″, @”[a1 isEqual:a2] should return YES”);

XCTAssertNotEqualObjects(a1, a2, format…) //判斷不等, [a1 isEqual:a2] 值為False時通過,
XCTAssertNotEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return NO”);
XCTAssertNotEqualObjects(@”1″, @”2″, @”[a1 isEqual:a2] should return NO”);

XCTAssertEqual(a1, a2, format…) //判斷相等(當a1和a2是 C語言標量、結構體或聯合體時使用,實際測試發現NSString也可以);
XCTAssertNotEqual(a1, a2, format…) //判斷不等(當a1和a2是 C語言標量、結構體或聯合體時使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…) 判斷相等,(double或float類型)//提供一個誤差範圍,當在誤差範圍(+/- accuracy )以內相等時通過測試;
XCTAssertEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return YES”);

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…) 判斷不等,(double或float類型)//提供一個誤差範圍,當在誤差範圍以內不等時通過測試;
XCTAssertNotEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return NO”);

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沒有發生具體異常、具體異常名稱的異常時通過測試,反之不通過;


//下面介紹一下測試元素的語法

XCUIApplication:
//繼承XCUIElement,這個類掌管應用程序的生命周期,裏面包含兩個主要方法
launch():
//啟動程序
terminate()
//終止程序

XCUIElement
//繼承NSObject,實現協議XCUIElementAttributes, XCUIElementTypeQueryProvider
//可以表示系統的各種UI元素
.exist
//可以讓你判斷當前的UI元素是否存在,如果對一個不存在的元素進行操作,會導致測試組件拋出異常並中斷測試
descendantsMatchingType(type:XCUIElementType)->XCUIElementQuery
//取某種類型的元素以及它的子類集合
childrenMatchingType(type:XCUIElementType)->XCUIElementQuery
//取某種類型的元素集合,不包含它的子類

//這兩個方法的區別在於,你僅使用系統的UIButton時,用childrenMatchingType就可以了,如果你還希望查詢自己定義的子Button,就要用descendantsMatchingType

//另外UI元素還有一些交互方法
tap()
//點擊
doubleTap()
//雙擊
pressForDuration(duration: NSTimeInterval)
//長按一段時間,在你需要進行延時操作時,這個就派上用場了
swipeUp()
//這個響應不了pan手勢,暫時沒發現能用在什麽地方,也可能是beta版的bug,先不解釋
typeText(text: String)
//用於textField和textView輸入文本時使用,使用前要確保文本框獲得輸入焦點,可以使用tap()函數使其獲得焦點

XCUIElementAttributes協議
//裏面包含了UIAccessibility中的部分屬性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

iOS 單元測試