前言
單元測試和UI測試大致步驟網(wǎng)上很多文章都有韭寸,如果會的可以忽略答姥,關鍵是錯誤總結(jié),網(wǎng)上很少有文章提及到,感興趣的讀者可以拉到最后面看看總結(jié)对蒲,相信你一定有所收獲!!!
unitTests測試
1.unitTests作用
由于只是一些簡單實用的東西,學學還是挺不錯的贡翘。其實單元測試用的好蹈矮,開發(fā)起來也會快很多。單元測試對于我目前來說鸣驱,就是為了方便測試一些功能是否正常運行泛鸟,還有調(diào)試接口是否能正常使用。有時候你可能是為了測試某一個網(wǎng)絡接口踊东,然后每次都重新啟動并且經(jīng)過很多操作之后才測試到了那個網(wǎng)絡接口北滥。如果使用了單元測試,就可以直接測試那個方法闸翅,相對方便很多再芋。 比如由于修改較多,我們想測試一下分享功能是否正常坚冀,這時候就有用了济赎。(而不是重新啟動程序,進入到分享界面记某,點擊分享司训,填寫分享內(nèi)容。)其實單元測試并沒有降低我們打代碼的效率液南,我們可以在單元測試通過了壳猜,直接用到相應的地方。
當然也有一些高級的作用贺拣,比如自動發(fā)布蓖谢、自動測試(特別在一些大的項目,以防止程序被誤改或引起新的問題)譬涡。
現(xiàn)在闪幽,讓我們先理清一下單元測試到底有些什么東西?
OCUnit(即用XCTest進行測試)其實就是蘋果自帶的測試框架涡匀,我們主要講的就是這個盯腌。GHUnit是一個可視化的測試框架。(有了它陨瘩,你可以點擊APP來決定測試哪個方法腕够,并且可以點擊查看測試結(jié)果等。)OCMock就是模擬某個方法或者屬性的返回值舌劳,你可能會疑惑為什么要這樣做?使用用模型生成的模型對象帚湘,再傳進去不就可以了?答案是可以的甚淡,但是有特殊的情況大诸。比如你測試的是方法A,方法A里面調(diào)用到了方法B贯卦,而且方法B是有參數(shù)傳入资柔,但又不是方法A所提供。這時候撵割,你可以使用OCMock來模擬方法B返回的值贿堰。(在不影響測試的情況下,就可以這樣去模擬啡彬。)除了這些羹与,在沒有網(wǎng)絡的情況下,也可以通過OCMock模擬返回的數(shù)據(jù)庶灿。UITests就是通過代碼化來實現(xiàn)自動點擊界面注簿,輸入文字等功能√拢靠人工操作的方式來覆蓋所有測試用例是非常困難的诡渴,尤其是加入新功能以后,舊的功能也要重新測試一遍菲语,這導致了測試需要花非常多的時間來進行回歸測試妄辩,這里產(chǎn)生了大量重復的工作,而這些重復的工作有些是可以自動完成的山上,這時候UITests就可以幫助解決這個問題了眼耀。
2.unitTests的使用
創(chuàng)建一個工程,名字隨便取佩憾,直接勾選include Unit Tests
萬一我忘了勾選怎么辦呢哮伟?可以有其他方式創(chuàng)建File-->new-->target-->iOS-->iOS Unit Testing Bundle干花。名字自己看著辦吧。
工程創(chuàng)建好后楞黄,那要怎么開始測試呢池凄?
找到系統(tǒng)單元測試Testes文件夾中.m文件看中會到看到幾個方法,我們來看下這個幾個方法是什么時候調(diào)用和他們各種的作用
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
//初始化的代碼鬼廓,在測試方法調(diào)用之前調(diào)用
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
// 釋放測試用例的資源代碼肿仑,這個方法會每個測試用例執(zhí)行后調(diào)用
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
// 測試用例的例子,注意測試用例一定要test開頭
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
// 測試性能例子
[self measureBlock:^{
// Put the code you want to measure the time of here.
// 需要測試性能的代碼
}];
}
在ViewController中寫一個簡單的方法
-(int)getNum;
實現(xiàn):
- (int)getNum {
return 100;
}
在測試的文件中導入ViewController.h碎税,并且定義一個vc屬性
#import
#import "ViewController.h"
@interface ____Tests : XCTestCase
@property (nonatomic,strong) ViewController *vc;
@end
@implementation ____Tests
//測試用例的實現(xiàn)
- (void)setUp {
[super setUp];
// 實例化需要測試的類
self.vc = [[ViewController alloc] init];
}
- (void)tearDown {
// 清空
self.vc = nil;
[super tearDown];
}
- (void)testMyFuc {
// 調(diào)用需要測試的方法尤慰,
int result = [self.vc getNum];
// 如果不相等則會提示@“測試不通過”
XCTAssertEqual(result, 100,@"測試不通過");
}
command+u快捷方式運行,或者produce-->test都行雷蹂,或只跑某個測試用例如圖
性能測試
3.使用的斷言種類
1.XCTFail(format…) 生成一個失敗的測試伟端;
2.XCTAssertNil(a1, format...)為空判斷,a1為空時通過匪煌,反之不通過荔泳;
3.XCTAssertNotNil(a1, format…)不為空判斷,a1不為空時通過虐杯,反之不通過玛歌;
4.XCTAssert(expression, format...)當expression求值為TRUE時通過;
5.XCTAssertTrue(expression, format...)當expression求值為TRUE時通過擎椰;
6.XCTAssertFalse(expression, format...)當expression求值為False時通過支子;
7.XCTAssertEqualObjects(a1, a2, format...)判斷相等,[a1 isEqual:a2]值為TRUE時通過达舒,其中一個不為空時值朋,不通過;
8.XCTAssertNotEqualObjects(a1, a2, format...)判斷不等巩搏,[a1 isEqual:a2]值為False時通過昨登;
9.XCTAssertEqual(a1, a2, format...)判斷相等(當a1和a2是 C語言標量、結(jié)構(gòu)體或聯(lián)合體時使用,實際測試發(fā)現(xiàn)NSString也可以)贯底;
10.XCTAssertNotEqual(a1, a2, format...)判斷不等(當a1和a2是 C語言標量丰辣、結(jié)構(gòu)體或聯(lián)合體時使用);
11.XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判斷相等禽捆,(double或float類型)提供一個誤差范圍笙什,當在誤差范圍(+/-accuracy)以內(nèi)相等時通過測試;
12.XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判斷不等胚想,(double或float類型)提供一個誤差范圍琐凭,當在誤差范圍以內(nèi)不等時通過測試;
13.XCTAssertThrows(expression, format...)異常測試浊服,當expression發(fā)生異常時通過统屈;反之不通過胚吁;(很變態(tài))
14.XCTAssertThrowsSpecific(expression, specificException, format...) 異常測試,當expression發(fā)生specificException異常時通過愁憔;反之發(fā)生其他異惩蠓觯或不發(fā)生異常均不通過;
15.XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)異常測試惩淳,當expression發(fā)生具體異常、具體異常名稱的異常時通過測試乓搬,反之不通過思犁;
16.XCTAssertNoThrow(expression, format…)異常測試,當expression沒有發(fā)生異常時通過測試进肯;
17.XCTAssertNoThrowSpecific(expression, specificException, format...)異常測試激蹲,當expression沒有發(fā)生具體異常、具體異常名稱的異常時通過測試江掩,反之不通過学辱;
18.XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)異常測試,當expression沒有發(fā)生具體異常环形、具體異常名稱的異常時通過測試策泣,反之不通過
特別注意下XCTAssertEqualObjects和XCTAssertEqual。
XCTAssertEqualObjects(a1, a2, format...)的判斷條件是[a1 isEqual:a2]是否返回一個YES抬吟。
XCTAssertEqual(a1, a2, format...)的判斷條件是a1 == a2是否返回一個YES萨咕。
對于后者,如果a1和a2都是基本數(shù)據(jù)類型變量火本,那么只有a1 == a2才會返回YES危队。
4.異步函數(shù)的單元測試
//waitForExpectationsWithTimeout是等待時間,超過了就不再等待往下執(zhí)行钙畔。
#define WAIT do {\
[self expectationForNotification:@"RSBaseTest" object:nil handler:nil];\
[self waitForExpectationsWithTimeout:30 handler:nil];\
} while (0);
#define NOTIFY \
[[NSNotificationCenter defaultCenter]postNotificationName:@"RSBaseTest" object:nil];
增加測試方法testRequest:
-(void)testRequest{
// 1.獲得請求管理者
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",nil];
// 2.發(fā)送GET請求
[mgr GET:@"http://www.weather.com.cn/adat/sk/101110101.html" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"responseObject:%@",responseObject);
XCTAssertNotNil(responseObject, @"返回出錯");
NOTIFY //繼續(xù)執(zhí)行
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"error:%@",error);
XCTAssertNil(error, @"請求出錯");
NOTIFY //繼續(xù)執(zhí)行
}];
WAIT//暫停
}
5.測試覆蓋率的查看
在運行測試之前茫陆,我們必須先確認 code coverage 是否被打開了,寫代碼時擎析,默認是關閉的簿盅。所以你需要編輯一下你的測試 scheme,把它打開揍魂。
確保"Gather coverage data"是被選中的挪鹏,然后點擊關閉按鈕,運行測試的 target. 我們希望剛剛創(chuàng)建的測試用例能夠順利通過愉烙。
Coverage Tab
一旦這個測試通過了讨盒,你就能知道 checkWord 這個方法,至少有一條路徑是對的步责。但你不知道的是返顺,還多多少沒有被測試到禀苦。這就是code coverage這個工具的好處。當你打開code coverage tab后遂鹊,你可以清楚的看到測試的覆蓋情況振乏。他們按找 target, file, function 進行了自動分組。
打開Xcode左邊窗口的Report Navigator面板秉扑,選中你剛運行的測試慧邮。然后在tab中選中 Coverage。
這會展示一個你的類舟陆、方法的列表误澳,并標示出每個的測試覆蓋率。如果你將鼠標懸停在checkWord這個方法上秦躯,你可以看到測試的覆蓋率是28%忆谓。不能接受啊踱承!我們需要找到倡缠,那些代碼分支是能夠被測試執(zhí)行,那些是不能的茎活,進而改善他們昙沦。雙擊方法的名字,Xcode會打開類的代碼载荔,并且看到code coverage的情況桅滋。
白色的區(qū)域表示這些代碼時測試覆蓋過的∩肀妫灰色區(qū)域時測試無法覆蓋的丐谋,我們需要添加更多的測試用例來覆蓋灰色部分的代碼。在右手邊的數(shù)字煌珊,表明這些代碼塊号俐,在這次測試中被執(zhí)行的次數(shù)。
UI測試
?可以參考這個網(wǎng)站?http://www.cocoachina.com/ios/20150702/12253.html 這里就不啰嗦了
總結(jié)UI測試遇到的問題 (重點)?
1.自動生成uitests字符亂碼問題
目前查閱資料只有\(zhòng)U變成\u,可以用查找工具替換掉,生成的unicode編碼也可以直接用中文替換;
2.uitests自動生成的代碼經(jīng)常報TimeStamped Event Matching Error:Failed to find matching element ,這個大多數(shù)原因是由于控件id變化導致的定庵,所以對于id動態(tài)變化一般都通過下標形式查找到相應的控件
Xcode自動產(chǎn)生的大多數(shù)是這樣:
[app.buttons[@"\u4e8c\u624b\u8f66\u4e16\u754c"] tap];
Demo:
[[[[[app.tables elementBoundByIndex:0] childrenMatchingType:XCUIElementTypeCell] elementBoundByIndex:4] childrenMatchingType:XCUIElementTypeTextField] elementBoundByIndex:0]
[app.XXX];獲得當前window上所有這種類型的控件
3.uitests textFiled不能通過identifier直接獲取到吏饿,利用錄制的話一般以點擊就會報錯誤;
4.descendantsMatchingType查找包含子類蔬浙,childrenMatchingType查找本類不包含子類猪落;
5.獲取的控件不知道存不存在時可以用exists判斷下,對沒有獲取到的控件操作直接會崩;
6.要特別注意彈出的視圖畴博,如果此時對后面一層視圖操作會出問題笨忌,如果能自動消失的,可以使用延遲pressForDuration: (NSTimeInterval)后在操作俱病,如果不會消失的要轉(zhuǎn)到這層操作官疲;
7.Assertion Failure: :0: UI Testing Failure - Failed to scroll to visible (by AX action) Image 0x600000175240: traits: 8589934596, {{172.0, 70.0}, {70.0, 70.0}}, identifier: 'Icon_Boy', error: Error -25204 performing AXAction 2003 //沒有滾到可見范圍的錯誤
[[[[[self.app.tables elementBoundByIndex:0] descendantsMatchingType:XCUIElementTypeAny] elementBoundByIndex:0]tap]; 報上面的錯誤
解決:[[[[[self.app.tables elementBoundByIndex:0] descendantsMatchingType:XCUIElementTypeAny] elementBoundByIndex:0] coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] tap];
coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5) 使用這個函數(shù)增加點偏移量即可,我試了0.5袱结,0.5 可以用,你們可以試試別的行不行途凫,目前我還不知道這個值是怎么確定的,我們需要做判斷用這個方法時垢夹,可以用isHittable這個判斷下是否可以點擊,如果是false维费,就用偏移的方法果元,如果返回為yes,就原來的方法即可
有時候放在tableview頭視圖的imageView,使用[[self.app.images elementBoundByIndex:0] tap]產(chǎn)生這種錯誤時犀盟,可以使用[[self.app.tables elementBoundByIndex:0] descendantsMatchingType:XCUIElementTypeAny] elementBoundByIndex:0] tap]解決
有任何問題可以@我哦
參考網(wǎng)址
http://www.reibang.com/p/009844a0b9edUnitTest(簡單的單元測試使用)
http://blog.csdn.net/it_ds/article/details/51286791UnitTest(簡單的單元測試使用)
http://www.reibang.com/p/8bbec078cabeUnitTest(有異步測試Demo)
http://www.reibang.com/p/254d6f9f0bc4UnitTest(利用GCD實現(xiàn)異步測試Demo)
http://www.cocoachina.com/ios/20150702/12253.html ? ?UITest
http://blog.sina.com.cn/s/blog_864456e50101ekqh.html斷言解釋說明
http://www.cnblogs.com/ziyi--caolu/p/4893847.htmlUnitTest(有測試實例代碼)
http://www.cocoachina.com/ios/20150915/13163.html單元測試覆蓋率
https://pan.baidu.com/s/1eR112i2自動化測試視頻地址