成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS自動(dòng)化測(cè)試的那些干貨

移動(dòng)開(kāi)發(fā) iOS 自動(dòng)化
自動(dòng)化測(cè)試就是寫(xiě)一些測(cè)試代碼,用代碼代替人工去完成模塊和業(yè)務(wù)的測(cè)試。其實(shí)不管是開(kāi)發(fā)還是測(cè)試,如果你在不斷的做重復(fù)性工作的時(shí)候,就應(yīng)該問(wèn)自己一個(gè)問(wèn)題:是不是有更高效的辦法?

前言

如果有測(cè)試大佬發(fā)現(xiàn)內(nèi)容不對(duì),歡迎指正,我會(huì)及時(shí)修改。

大多數(shù)的iOS App(沒(méi)有持續(xù)集成)迭代流程是這樣的   

iOS App(沒(méi)有持續(xù)集成)迭代流程 

也就是說(shuō),測(cè)試是發(fā)布之前的最后一道關(guān)卡。如果bug不能在測(cè)試中發(fā)現(xiàn),那么bug

就會(huì)抵達(dá)用戶(hù),所以測(cè)試的完整性和可靠性十分重要。

目前,大多數(shù)App還停留在人工測(cè)試階段,人工測(cè)試投入的成本最低,能夠保證核心功能的使用,而且測(cè)試人員不需要會(huì)寫(xiě)代碼。

但是,在很多測(cè)試場(chǎng)景下,人工測(cè)試的效率太低,容易出錯(cuò)。舉兩個(gè)常見(jiàn)的例子:

  • 一個(gè)App的核心功能,在每一次發(fā)布版本前的測(cè)試必定會(huì)跑一遍所有的測(cè)試用例,不管對(duì)應(yīng)的業(yè)務(wù)在當(dāng)前版本有沒(méi)有變化(天知道開(kāi)發(fā)在做業(yè)務(wù)A的時(shí)候,對(duì)業(yè)務(wù)B有沒(méi)有影響),如果這次測(cè)出新的bug,測(cè)試人員在下一次發(fā)版測(cè)試中,又不得不做這些重復(fù)的工作。
  • 開(kāi)發(fā)在寫(xiě)API請(qǐng)求相關(guān)代碼的時(shí)候沒(méi)有做數(shù)據(jù)容錯(cuò),測(cè)試在人工測(cè)試的時(shí)候都是正常的數(shù)據(jù),所以測(cè)試通過(guò)。上線(xiàn)了之后,后臺(tái)配置數(shù)據(jù)的時(shí)候出了點(diǎn)小問(wèn)題,導(dǎo)致大面積崩潰,boom~。

然后,老板就要過(guò)來(lái)找你了  

 

[[187977]] 

本文所講解的均是基于XCode 8.2.1,有些概念可能不適用于低版本的XCode

自動(dòng)化測(cè)試

自動(dòng)化測(cè)試就是寫(xiě)一些測(cè)試代碼,用代碼代替人工去完成模塊和業(yè)務(wù)的測(cè)試。

其實(shí)不管是開(kāi)發(fā)還是測(cè)試,如果你在不斷的做重復(fù)性工作的時(shí)候,就應(yīng)該問(wèn)自己一個(gè)問(wèn)題:是不是有更高效的辦法?

自動(dòng)化測(cè)試有很多優(yōu)點(diǎn):

  • 測(cè)試速度快,避免重復(fù)性的工作
  • 避免regression,讓開(kāi)發(fā)更有信心去修改和重構(gòu)代碼(個(gè)人認(rèn)為最大的優(yōu)點(diǎn))
  • 具有一致性。
  • 有了自動(dòng)化測(cè)試,持續(xù)集成(CI)會(huì)變得更可靠。
  • 迫使開(kāi)發(fā)人員寫(xiě)出更高質(zhì)量的代碼。(自動(dòng)化測(cè)試不通過(guò),代碼不允許合并)

當(dāng)然,自動(dòng)化測(cè)試也有一些缺點(diǎn)。

  • 開(kāi)發(fā)和維護(hù)成本高。
  • 不能完全替代人工測(cè)試。
  • 無(wú)法完全保證測(cè)試的準(zhǔn)確性 – 讓代碼去判斷一段邏輯是否正確很容易,但是,讓代碼判斷一個(gè)控件顯示是否正確卻沒(méi)那么容易。

所以,在做自動(dòng)化測(cè)試之前,首先要問(wèn)自己幾個(gè)問(wèn)題?

  • 這個(gè)測(cè)試業(yè)務(wù)的變動(dòng)是否頻繁?
  • 這個(gè)測(cè)試業(yè)務(wù)是否屬于核心功能?
  • 編寫(xiě)測(cè)試代碼的成本有多少?
  • 自動(dòng)化測(cè)試能保證測(cè)試結(jié)果的準(zhǔn)確么?

通常,我們會(huì)選擇那些業(yè)務(wù)穩(wěn)定,需要頻繁測(cè)試的部分來(lái)編寫(xiě)自動(dòng)化測(cè)試腳本,其余的采用人工測(cè)試,人工測(cè)試仍然是iOS App開(kāi)發(fā)中不可缺少的一部分。

測(cè)試種類(lèi)

從是否接觸源代碼的角度來(lái)分類(lèi):測(cè)試分為黑盒和白盒(灰盒就是黑盒白盒結(jié)合,這里不做討論)。

白盒測(cè)試的時(shí)候,測(cè)試人員是可以直接接觸待測(cè)試App的源代碼的。白盒測(cè)試更多的是單元測(cè)試,測(cè)試人員針對(duì)各個(gè)單元進(jìn)行各種可能的輸入分析,然后測(cè)試其輸出。白盒測(cè)試的測(cè)試代碼通常由iOS開(kāi)發(fā)編寫(xiě)。

黑盒測(cè)試。黑盒測(cè)試的時(shí)候,測(cè)試人員不需要接觸源代碼。是從App層面對(duì)其行為以及UI的正確性進(jìn)行驗(yàn)證,黑盒測(cè)試由iOS測(cè)試完成。

從業(yè)務(wù)的層次上來(lái)說(shuō),測(cè)試金字塔如圖:   

[[187978]] 

而iOS測(cè)試通常只有以下兩個(gè)層次:

  • Unit,單元測(cè)試,保證每一個(gè)類(lèi)能夠正常工作
  • UI,UI測(cè)試,也叫做集成測(cè)試,從業(yè)務(wù)層的角度保證各個(gè)業(yè)務(wù)可以正常工作。

框架選擇

啰里八嗦講的這么多,自動(dòng)化測(cè)試的效率怎么樣,關(guān)鍵還是在測(cè)試框架上。那么,如何選擇測(cè)試框架呢?框架可以分為兩大類(lèi):XCode內(nèi)置的和三方庫(kù)。

選擇框架的時(shí)候有幾個(gè)方面要考慮

  • 測(cè)試代碼編寫(xiě)的成本
  • 是否可調(diào)式
  • 框架的穩(wěn)定性
  • 測(cè)試報(bào)告(截圖,代碼覆蓋率,…)
  • WebView的支持(很多App都用到了H5)
  • 自定義控件的測(cè)試
  • 是否需要源代碼
  • 能否需要連著電腦
  • 是否支持CI(持續(xù)集成)
  • ….

我們首先來(lái)看看XCode內(nèi)置的框架:XCTest。XCTest又可以分為兩部分:Unit Test 和 UI Test,分別對(duì)應(yīng)單元測(cè)試和UI測(cè)試。有一些三方的測(cè)試庫(kù)也是基于XCTest框架的,這個(gè)在后文會(huì)講到。由于是Apple官方提供的,所以這個(gè)框架會(huì)不斷完善。

成熟的三方框架通常提供了很多封裝好的有好的接口,筆者綜合對(duì)比了一些,推薦以下框架:

單元測(cè)試:

以下三個(gè)框架都是BDD(Behavior-driven development) – 行為驅(qū)動(dòng)開(kāi)發(fā)。行為驅(qū)動(dòng)開(kāi)發(fā)簡(jiǎn)單來(lái)說(shuō)就是先定義行為,然后定義測(cè)試用例,接著再編寫(xiě)代碼。 實(shí)踐中發(fā)現(xiàn),通常沒(méi)有那么多時(shí)間來(lái)先定義行為,不過(guò)BDD中的domain-specific language (DSL)能夠很好的描述用例的行為。

  • Kiwi 老牌測(cè)試框架
  • specta 另一個(gè)BDD優(yōu)秀框架
  • Quick 三個(gè)項(xiàng)目中Star最多,支持OC和Swift,優(yōu)先推薦。

UI測(cè)試

  • KIF 基于XCTest的測(cè)試框架,調(diào)用私有API來(lái)控制UI,測(cè)試用例用Objective C或Swift編寫(xiě)。
  • appium 基于Client – Server的測(cè)試框架。App相當(dāng)于一個(gè)Server,測(cè)試代碼相當(dāng)于Client,通過(guò)發(fā)送JSON來(lái)操作APP,測(cè)試語(yǔ)言可以是任意的,支持android和iOS。

篇幅有限,本文會(huì)先介紹XCtest,接著三方的Unit框架會(huì)以Quick為例,UI Test框架側(cè)重分析KIF,appium僅僅做原理講解。

XCTest

對(duì)于XCTest來(lái)說(shuō),最后生成的是一個(gè)bundle。bundle是不能直接執(zhí)行的,必須依賴(lài)于一個(gè)宿主進(jìn)程。關(guān)于XCTest進(jìn)行單元測(cè)試的基礎(chǔ)(XCode的使用,異步測(cè)試,性能測(cè)試,代碼覆蓋率等),我在這篇文章里講解過(guò),這里不再詳細(xì)講解。

  • iOS 單元測(cè)試之XCTest詳解

blog.csdn.net/hello_hwc/article/details/46671053

單元測(cè)試用例

比如,我有以下一個(gè)函數(shù):

  1. //驗(yàn)證一段Text是否有效。(不能以空字符開(kāi)頭,不能為空) 
  2.  
  3. - (BOOL)validText:(NSString *)text error:(NSError *__autoreleasing *)error{ 
  4.  
  5.  

那么,我該如何為這個(gè)函數(shù)編寫(xiě)單元測(cè)試的代碼?通常,需要考慮以下用例:

  1. 輸入以空白字符或者換行符開(kāi)頭的,error不為空,返回 NO
  2. 輸入正確的內(nèi)容,error為空,返回YES
  3. 輸入為nil,error不為空,返回 NO (邊界條件)
  4. 輸入為非NSString類(lèi)型,驗(yàn)證不通過(guò),返回NO (錯(cuò)誤輸入)
  5. 特殊輸入字符(標(biāo)點(diǎn)符號(hào),非英文等等)

UI測(cè)試

UI測(cè)試是模擬用戶(hù)操作,進(jìn)而從業(yè)務(wù)處層面測(cè)試。關(guān)于XCTest的UI測(cè)試,建議看看WWDC 2015的這個(gè)視頻:

  • UI Testing in Xcode

https://developer.apple.com/videos/play/wwdc2015/406/

關(guān)于UI測(cè)試,有幾個(gè)核心類(lèi)需要掌握

  • XCUIApplication 測(cè)試應(yīng)用的代理
  • XCUIElement 一個(gè)UI上可見(jiàn)的視圖對(duì)象
  • XCUIElementQuery 查找XCUIElement

UI測(cè)試還有一個(gè)核心功能是UI Recording。選中一個(gè)UI測(cè)試用例,然后點(diǎn)擊圖中的小紅點(diǎn)既可以開(kāi)始UI Recoding。你會(huì)發(fā)現(xiàn):

隨著點(diǎn)擊模擬器,自動(dòng)合成了測(cè)試代碼。(通常自動(dòng)合成代碼后,還需要手動(dòng)的去調(diào)整)  

 

在寫(xiě)UI測(cè)試用例的時(shí)候要注意:測(cè)試行為而不是測(cè)試代碼。比如,我們測(cè)試這樣一個(gè)case

進(jìn)入Todo首頁(yè),點(diǎn)擊add,進(jìn)入添加頁(yè)面,輸入文字,點(diǎn)擊save。

測(cè)試效果如下:  

 

 

對(duì)應(yīng)測(cè)試代碼:

  1. - (void)testAddNewItems{ 
  2.  
  3.     //獲取app代理 
  4.  
  5.     XCUIApplication *app = [[XCUIApplication alloc] init]; 
  6.  
  7.     //找到第一個(gè)tabeview,就是我們想要的tableview 
  8.  
  9.     XCUIElement * table = [app.tables elementBoundByIndex:0]; 
  10.  
  11.     //記錄下來(lái)添加之前的數(shù)量 
  12.  
  13.     NSInteger oldCount = table.cells.count
  14.  
  15.     //點(diǎn)擊Add 
  16.  
  17.     [app.navigationBars[@"ToDo"].buttons[@"Add"] tap]; 
  18.  
  19.     //找到Textfield 
  20.  
  21.     XCUIElement *inputWhatYouWantTodoTextField = app.textFields[@"Input what you want todo"]; 
  22.  
  23.     //點(diǎn)擊Textfield 
  24.  
  25.     [inputWhatYouWantTodoTextField tap]; 
  26.  
  27.     //輸入字符 
  28.  
  29.     [inputWhatYouWantTodoTextField typeText:@"somethingtodo"]; 
  30.  
  31.     //點(diǎn)擊保存 
  32.  
  33.     [app.navigationBars[@"Add"].buttons[@"Save"] tap]; 
  34.  
  35.     //獲取當(dāng)前的數(shù)量 
  36.  
  37.     NSInteger newCount = table.cells.count
  38.  
  39.     //如果cells的數(shù)量加一,則認(rèn)為測(cè)試成功 
  40.  
  41.     XCTAssert(newCount == oldCount + 1); 
  42.  
  43.  

這里是通過(guò)前后tableview的row數(shù)量來(lái)斷言成功或者失敗。

等待

通常,在視圖切換的時(shí)候有轉(zhuǎn)場(chǎng)動(dòng)畫(huà),我們需要等待動(dòng)畫(huà)結(jié)束,然后才能繼續(xù),否則query的時(shí)候很可能找不到我們想要的控件。

比如,如下代碼等待VC轉(zhuǎn)場(chǎng)結(jié)束,當(dāng)query只有一個(gè)table的時(shí)候,才繼續(xù)執(zhí)行后續(xù)的代碼。

  1. [self expectationForPredicate:[NSPredicate predicateWithFormat:@"self.count = 1"
  2.  
  3.           evaluatedWithObject:app.tables 
  4.  
  5.                       handler:nil]; 
  6.  
  7. [self waitForExpectationsWithTimeout:2.0 handler:nil]; 
  8.  
  9. //后續(xù)代碼....  

Tips: 當(dāng)你的UI結(jié)構(gòu)比較復(fù)雜的時(shí)候,比如各種嵌套childViewController,使用XCUIElementQuery的代碼會(huì)很長(zhǎng),也不好維護(hù)。

另外,UI測(cè)試還會(huì)在每一步操作的時(shí)候截圖,方便對(duì)測(cè)試報(bào)告進(jìn)行驗(yàn)證。

查看測(cè)試結(jié)果

使用基于XCTest的框架,可以在XCode的report navigator中查看測(cè)試結(jié)果。   

 

其中:

  • Tests 用來(lái)查看詳細(xì)的測(cè)試過(guò)程
  • Coverage 用來(lái)查看代碼覆蓋率
  • Logs 用來(lái)查看測(cè)試的日志
  • 點(diǎn)擊圖中的紅色框指向的圖標(biāo)可以看到每一步UI操作的截圖

除了利用XCode的GUI,還可以通過(guò)后文提到的命令行工具來(lái)測(cè)試,查看結(jié)果。

Stub/Mock

首先解釋兩個(gè)術(shù)語(yǔ):

  • mock 表示一個(gè)模擬對(duì)象
  • stub 追蹤方法的調(diào)用,在方法調(diào)用的時(shí)候返回指定的值。

通常,如果你采用純存的XCTest,推薦采用OCMock來(lái)實(shí)現(xiàn)mock和stub,單元測(cè)試的三方庫(kù)通常已集成了stub和mock。

那么,如何使用mock呢?舉個(gè)官方的例子:

  1. //mock一個(gè)NSUserDefaults對(duì)象 
  2.  
  3. id userDefaultsMock = OCMClassMock([NSUserDefaults class]); 
  4.  
  5. //在調(diào)用stringForKey的時(shí)候,返回http://testurl 
  6.  
  7. OCMStub([userDefaultsMock 
  8.  
  9. stringForKey:@"MyAppURLKey"]).andReturn(@"http://testurl");  

再比如,我們要測(cè)試打開(kāi)其他App,那么如何判斷確實(shí)打開(kāi)了其他App呢?

  1. id app = OCMClassMock([UIApplication class]); 
  2.  
  3. OCMStub([app sharedInstance]).andReturn(app); 
  4.  
  5. OCMVerify([app openURL:url]   

使用Stub可以讓我們很方便的實(shí)現(xiàn)這個(gè)。

關(guān)于OCMock的使用,推薦看看objc.io的這篇文章

  • 置換測(cè)試: Mock, Stub 和其他

https://objccn.io/issue-15-5/

Quick

Quick是建立在XCTestSuite上的框架,使用XCTestSuite允許你動(dòng)態(tài)創(chuàng)建測(cè)試用例。所以,使用Quick,你仍讓可以使用XCode的測(cè)試相關(guān)GUI和命令行工具。

使用Quick編寫(xiě)的測(cè)試用例看起來(lái)是這樣子的:

  1. import Quick 
  2.  
  3. import Nimble 
  4.  
  5.   
  6.  
  7. class TableOfContentsSpec: QuickSpec { 
  8.  
  9.   override func spec() { 
  10.  
  11.     describe("the 'Documentation' directory") { 
  12.  
  13.       it("has everything you need to get started") { 
  14.  
  15.         let sections = Directory("Documentation").sections 
  16.  
  17.         expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups")) 
  18.  
  19.         expect(sections).to(contain("Installing Quick")) 
  20.  
  21.       } 
  22.  
  23.   
  24.  
  25.       context("if it doesn't have what you're looking for") { 
  26.  
  27.         it("needs to be updated") { 
  28.  
  29.           let you = You(awesome: true
  30.  
  31.           expect{you.submittedAnIssue}.toEventually(beTruthy()) 
  32.  
  33.         } 
  34.  
  35.       } 
  36.  
  37.     } 
  38.  
  39.   } 
  40.  
  41.  

BDD的框架讓測(cè)試用例的目的更加明確,測(cè)試是否通過(guò)更加清晰。使用Quick,測(cè)試用例分為兩種:

單獨(dú)的用例 – 使用it來(lái)描述

it有兩個(gè)參數(shù),

  • 行為描述
  • 行為的測(cè)試代碼

比如,以下測(cè)試Dolphin行為,它具有行為is friendly和is smart

  1. //Swift代碼 
  2.  
  3. class DolphinSpec: QuickSpec { 
  4.  
  5.   override func spec() { 
  6.  
  7.     it("is friendly") { 
  8.  
  9.       expect(Dolphin().isFriendly).to(beTruthy()) 
  10.  
  11.     } 
  12.  
  13.   
  14.  
  15.     it("is smart") { 
  16.  
  17.       expect(Dolphin().isSmart).to(beTruthy()) 
  18.  
  19.     } 
  20.  
  21.   } 
  22.  
  23.  

可以看到,BDD的核心是行為。也就是說(shuō),需要關(guān)注的是一個(gè)類(lèi)提供哪些行為。

用例集合,用describe和context描述

比如,驗(yàn)證dolphin的click行為的時(shí)候,我們需要兩個(gè)用例。一個(gè)是is loud,一個(gè)是has a high frequency,就可以用describe將用例組織起來(lái)。

  1. class DolphinSpec: QuickSpec { 
  2.  
  3.   override func spec() { 
  4.  
  5.     describe("a dolphin") { 
  6.  
  7.       describe("its click") { 
  8.  
  9.         it("is loud") { 
  10.  
  11.           let click = Dolphin().click() 
  12.  
  13.           expect(click.isLoud).to(beTruthy()) 
  14.  
  15.         } 
  16.  
  17.   
  18.  
  19.         it("has a high frequency") { 
  20.  
  21.           let click = Dolphin().click() 
  22.  
  23.           expect(click.hasHighFrequency).to(beTruthy()) 
  24.  
  25.         } 
  26.  
  27.       } 
  28.  
  29.     } 
  30.  
  31.   } 
  32.  
  33.  

context可以指定用例的條件:

比如

  1. describe("its click") { 
  2.  
  3.     context("when the dolphin is not near anything interesting") { 
  4.  
  5.       it("is only emitted once") { 
  6.  
  7.         expect(dolphin!.click().count).to(equal(1)) 
  8.  
  9.       } 
  10.  
  11.     } 
  12.  
  13.  

除了這些之外,Quick也支持一些切入點(diǎn),進(jìn)行測(cè)試前的配置:

  • beforeEach
  • afterEach
  • beforeAll
  • afterAll
  • beforeSuite
  • afterSuite

Nimble

由于Quick是基于XCTest,開(kāi)發(fā)者當(dāng)然可以收使用斷言來(lái)定義測(cè)試用例成功或者失敗。Quick提供了一個(gè)更有好的Framework來(lái)進(jìn)行這種斷言:https://github.com/Quick/Nimble

比如,一個(gè)常見(jiàn)的XCTest斷言如下:

  1. XCTAssertTrue(ConditionCode, "FailReason"

在出錯(cuò)的時(shí)候,會(huì)提示

  1. XCAssertTrue failed, balabala 

這時(shí)候,開(kāi)發(fā)者要打個(gè)斷點(diǎn),查看下上下文,看看具體失敗的原因在哪。

使用Nimble后,斷言變成類(lèi)似

  1. expect(1 + 1).to(equal(2)) 
  2.  
  3. expect(3) > 2 
  4.  
  5. expect("seahorse").to(contain("sea")) 
  6.  
  7. expect(["Atlantic""Pacific"]).toNot(contain("Mississippi"))  

并且,出錯(cuò)的時(shí)候,提示信息會(huì)帶著上下文的值信息,讓開(kāi)發(fā)者更容易的找到錯(cuò)誤。

讓你的代碼更容易單元測(cè)試

測(cè)試的準(zhǔn)確性和工作量很大程度上依賴(lài)于開(kāi)發(fā)人員的代碼質(zhì)量。

通常,為了單元測(cè)試的準(zhǔn)確性,我們?cè)趯?xiě)函數(shù)(方法)的時(shí)候會(huì)借鑒一些函數(shù)式編程的思想。其中最重要的一個(gè)思想就是

  • pure function(純函數(shù))

何為Pure function?就是如果一個(gè)函數(shù)的輸入一樣,那么輸出一定一樣。

比如,這樣的一個(gè)函數(shù)就不是pure function。因?yàn)樗蕾?lài)于外部變量value的值。

  1. static NSInteger value = 0; 
  2.  
  3.   
  4.  
  5. - (NSInteger)function_1{ 
  6.  
  7.     value = value + 1; 
  8.  
  9.     return value; 
  10.  
  11.  

而這個(gè)函數(shù)就是pure function,因?yàn)榻o定輸入,輸出一定一致。

  1. - (NSInteger)function_2:(NSInteger)base{ 
  2.  
  3.     NSInteger value = base + 1; 
  4.  
  5.     return value; 
  6.  
  7.  

所以,如果你寫(xiě)了一個(gè)沒(méi)有參數(shù),或者沒(méi)有返回值的方法,那么你要小心了,很可能這個(gè)方法很難測(cè)試。

關(guān)于MVC

在良好的MVC架構(gòu)的App中,

  • View只做純粹的展示型工作,把用戶(hù)交互通過(guò)各種方式傳遞到外部
  • Model只做數(shù)據(jù)存儲(chǔ)類(lèi)工作
  • Controller作為View和Model的樞紐,往往要和很多View和Model進(jìn)行交互,也是自動(dòng)化包括代碼維護(hù)的痛點(diǎn)。

所以,對(duì)Controller瘦身是iOS架構(gòu)中比較重要的一環(huán),一些通用的技巧包括:

邏輯抽離:

  • 網(wǎng)絡(luò)請(qǐng)求獨(dú)立。可以每個(gè)網(wǎng)絡(luò)請(qǐng)求以Command模式封裝成一個(gè)對(duì)象,不要直接在Controller調(diào)用AFNetworking。
  • 數(shù)據(jù)存儲(chǔ)獨(dú)立。建立獨(dú)立的Store類(lèi),用來(lái)做數(shù)據(jù)持久化和緩存。
  • 共有數(shù)據(jù)服務(wù)化(協(xié)議)。比如登錄狀態(tài)等等,通過(guò)服務(wù)去訪(fǎng)問(wèn),這樣服務(wù)提供者之需要處理服務(wù)的質(zhì)量,服務(wù)使用者則信任服務(wù)提供者的結(jié)果。

Controller與View解耦合

  • 建立ViewModel層,這樣Controller只需要和ViewModel進(jìn)行交互。
  • 建立UIView子類(lèi)作為容器,將一些View放到容器后再把容器作為SubView添加到Controller里
  • 建立可復(fù)用的Layout層,不管是AutoLayout還是手動(dòng)布局。

Controller與Controller解耦合

  • 建立頁(yè)面路由。每一個(gè)界面都抽象為一個(gè)URL,跳轉(zhuǎn)僅僅通過(guò)Intent或者URL跳轉(zhuǎn),這樣兩個(gè)Controller完全獨(dú)立。

如果你的App用Swift開(kāi)發(fā),那么面向協(xié)議編程和不可變的值類(lèi)型會(huì)讓你的代碼更容易測(cè)試。

當(dāng)然,iOS組建化對(duì)自動(dòng)化測(cè)試的幫助也很大,因?yàn)椴还苁腔A(chǔ)組件還是業(yè)務(wù)組件,都可以獨(dú)立測(cè)試。組建化又是一個(gè)很大的課題,這里不深入講解了。

KIF

KIF的全稱(chēng)是Keep it functional。它是一個(gè)建立在XCTest的UI測(cè)試框架,通過(guò)accessibility來(lái)定位具體的控件,再利用私有的API來(lái)操作UI。由于是建立在XCTest上的,所以你可以完美的借助XCode的測(cè)試相關(guān)工具(包括命令行腳本)。

> KIF是個(gè)人非常推薦的一個(gè)框架,簡(jiǎn)單易用。

使用KIF框架強(qiáng)制要求你的代碼支持accessibility。如果你之前沒(méi)接觸過(guò),可以看看Apple的文檔

  • Accessibility Programming Guide for iOS

https://developer.apple.com/library/prerelease/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html

簡(jiǎn)單來(lái)說(shuō),accessibility能夠讓視覺(jué)障礙人士使用你的App。每一個(gè)控件都有一個(gè)描述AccessibilityLabel。在開(kāi)啟VoiceOver的時(shí)候,點(diǎn)擊控件就可以選中并且聽(tīng)到對(duì)應(yīng)的描述。

通常UIKit的控件是支持accessibility的,自定定義控件可以通過(guò)代碼或者Storyboard上設(shè)置。

在Storyboard上設(shè)置:   

 

  • 上面的通過(guò)Runtime Attributes設(shè)置(KVC)
  • 下面的通過(guò)GUI來(lái)設(shè)置

通過(guò)代碼設(shè)置:

  1. [alert setAccessibilityLabel:@"Label"]; 
  2.  
  3. [alert setAccessibilityValue:@"Value"]; 
  4.  
  5. [alert setAccessibilityTraits:UIAccessibilityTraitButton];  

如果你有些Accessibility的經(jīng)驗(yàn),那么你肯定知道,像TableView的這種不應(yīng)該支持VoiceOver的。我們可以用條件編譯來(lái)只對(duì)測(cè)試Target進(jìn)行設(shè)置:

  1. #ifdef DEBUG 
  2.  
  3. [tableView setAccessibilityValue:@"Main List Table"]; 
  4.  
  5. #endif 
  6.  
  7.   
  8.  
  9. #ifdef KIF_TARGET (這個(gè)值需要在build settings里設(shè)置) 
  10.  
  11. [tableView setAccessibilityValue:@"Main List Table"]; 
  12.  
  13. #endif  

使用KIF主要有兩個(gè)核心類(lèi):

  • KIFTestCase XCTestCase的子類(lèi)
  • KIFUITestActor 控制UI,常見(jiàn)的三種是:點(diǎn)擊一個(gè)View,向一個(gè)View輸入內(nèi)容,等待一個(gè)View的出現(xiàn)

我們用KIF來(lái)測(cè)試添加一個(gè)新的ToDo

  1. - (void)testAddANewItem{ 
  2.  
  3.     [tester tapViewWithAccessibilityLabel:@"Add"]; 
  4.  
  5.     [tester enterText:@"Create a test to do item" intoViewWithAccessibilityLabel:@"Input what you want todo"]; 
  6.  
  7.     [tester tapViewWithAccessibilityLabel:@"Save"]; 
  8.  
  9.     [tester waitForTimeInterval:0.2]; 
  10.  
  11.     [tester waitForViewWithAccessibilityLabel:@"Create a test to do item"]; 
  12.  
  13.  

命令行

自動(dòng)化測(cè)試中,命令行工具可以facebook的開(kāi)源項(xiàng)目:

  • xctool

這是一個(gè)基于xcodebuild命令的擴(kuò)展,在iOS自動(dòng)化測(cè)試和持續(xù)集成領(lǐng)域很有用,而且它支持-parallelize并行測(cè)試多個(gè)bundle,大大提高測(cè)試效率。

安裝XCTool,

  1. brew install xctool 

使用

  1. path/to/xctool.sh \ 
  2.  
  3.   -workspace YourWorkspace.xcworkspace \ 
  4.  
  5.   -scheme YourScheme \ 
  6.  
  7.   -reporter plain:/path/to/plain-output.txt \ 
  8.  
  9.   run-test  

并且,xctool對(duì)于持續(xù)集成很有用,iOS常用的持續(xù)集成的server有兩個(gè):

  • Travis CI 對(duì)于公開(kāi)倉(cāng)庫(kù)(比如github)免費(fèi),私有倉(cāng)庫(kù)收費(fèi)
  • Jenkins 免費(fèi)

優(yōu)化你的測(cè)試代碼

準(zhǔn)確的測(cè)試用例

通常,你的你的測(cè)試用例分為三部分:

  • 配置測(cè)試的初始狀態(tài)
  • 對(duì)要測(cè)試的目標(biāo)執(zhí)行代碼
  • 對(duì)測(cè)試結(jié)果進(jìn)行斷言(成功 or 失敗)

測(cè)試代碼結(jié)構(gòu)

當(dāng)測(cè)試用例多了,你會(huì)發(fā)現(xiàn)測(cè)試代碼編寫(xiě)和維護(hù)也是一個(gè)技術(shù)活。通常,我們會(huì)從幾個(gè)角度考慮:

  • 不要測(cè)試私有方法(封裝是OOP的核心思想之一,不要為了測(cè)試破壞封裝)
  • 對(duì)用例分組(功能,業(yè)務(wù)相似)
  • 對(duì)單個(gè)用例保證測(cè)試獨(dú)立(不受之前測(cè)試的影響,不影響之后的測(cè)試),這也是測(cè)試是否準(zhǔn)確的核心。
  • 提取公共的代碼和操作,減少copy/paste這類(lèi)工作,測(cè)試用例是上層調(diào)用,只關(guān)心業(yè)務(wù)邏輯,不關(guān)心內(nèi)部代碼實(shí)現(xiàn)。

一個(gè)常見(jiàn)的測(cè)試代碼組織如下:   

 

appium

appium采用了Client Server的模式。對(duì)于A(yíng)pp來(lái)說(shuō)就是一個(gè)Server,基于WebDriver JSON wire protocol對(duì)實(shí)際的UI操作庫(kù)進(jìn)行了封裝,并且暴露出RESTFUL的接口。然后測(cè)試代碼通過(guò)HTTP請(qǐng)求的方式,來(lái)進(jìn)行實(shí)際的測(cè)試。其中,實(shí)際驅(qū)動(dòng)UI的框架根據(jù)系統(tǒng)版本有所不同:

  • < 9.3 采用UIAutomation
  • >= 9.3 XCUITest

原因也比較簡(jiǎn)單:Apple在10.0之后,移除了UIAutomation的支持,只支持XCUITest。   

 

對(duì)比KIF,appium有它的優(yōu)點(diǎn):

  • 跨平臺(tái),支持iOS,Android
  • 測(cè)試代碼可以由多種語(yǔ)言編寫(xiě),這對(duì)測(cè)試來(lái)說(shuō)門(mén)檻更低
  • 測(cè)試腳本獨(dú)立與源代碼和測(cè)試框架

當(dāng)然,任何框架都有缺點(diǎn):

  • 自定義控件支持不好
  • WebView的支持不好

總結(jié)

由于我不是專(zhuān)業(yè)的iOS測(cè)試,關(guān)于測(cè)試的一點(diǎn)見(jiàn)解如下:

  • 單元測(cè)試還是選擇BDD框架,畢竟可讀性高一些,推薦Quick(Swift),Kiwi(Objective C)
  • UI測(cè)試優(yōu)先推薦KIF,如果需要兼顧安卓測(cè)試,或者測(cè)試人員對(duì)OC/Swift很陌生,可以采用appium

參考資料

  • Testing with Xcode 官方文檔,關(guān)于XCTest以及XCode有詳細(xì)的講解
  • objc.io關(guān)于測(cè)試的資料對(duì)于官方文檔的補(bǔ)充
  • 騰訊移動(dòng)品質(zhì)中心 鵝廠(chǎng)移動(dòng)品質(zhì)中心,有很多好文章,強(qiáng)力推薦。
  • 基于 KIF 的 iOS UI 自動(dòng)化測(cè)試和持續(xù)集成 美團(tuán)點(diǎn)評(píng)技術(shù)團(tuán)隊(duì)寫(xiě)的一篇博客
  • testing-in-swift
  • 微信讀書(shū)排版引擎自動(dòng)化測(cè)試方案 

 

責(zé)任編輯:龐桂玉 來(lái)源: iOS大全
相關(guān)推薦

2014-04-16 14:15:01

QCon2014

2012-02-27 17:34:12

Facebook自動(dòng)化

2022-02-17 10:37:16

自動(dòng)化開(kāi)發(fā)團(tuán)隊(duì)預(yù)測(cè)

2023-03-27 15:37:43

自動(dòng)化測(cè)試開(kāi)發(fā)

2022-05-10 11:18:42

自動(dòng)化測(cè)試軟件測(cè)試

2022-06-08 14:22:55

自動(dòng)化測(cè)試測(cè)試

2021-09-03 09:56:18

鴻蒙HarmonyOS應(yīng)用

2013-05-16 10:58:44

Android開(kāi)發(fā)自動(dòng)化測(cè)試

2017-07-21 09:14:21

2011-12-23 17:09:57

自動(dòng)化測(cè)試

2022-12-04 23:52:11

iOS自動(dòng)化工具

2021-06-30 19:48:21

前端自動(dòng)化測(cè)試Vue 應(yīng)用

2012-12-24 22:54:31

2024-11-01 15:05:12

2023-06-28 15:12:33

2023-11-01 10:18:10

自動(dòng)化測(cè)試工具

2014-11-20 13:49:15

2011-06-03 17:24:48

自動(dòng)化測(cè)試

2011-05-30 17:31:26

自動(dòng)化測(cè)試

2011-01-20 10:17:25

ibmdwWeb
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人深夜福利网站 | 亚洲视频免费在线播放 | 99re在线视频| 人成精品 | 麻豆一区一区三区四区 | a在线v| 亚洲色图50p | 天天色综 | 91九色视频 | 精品亚洲国产成av人片传媒 | 天堂一区二区三区四区 | 久久人操| 一区二区三区四区免费视频 | 81精品国产乱码久久久久久 | 欧美中文字幕一区二区三区 | 高清国产一区二区 | 不卡av在线| 国产999精品久久久久久 | 国产日韩中文字幕 | 亚洲精品久久久久中文字幕欢迎你 | 国产草草视频 | jav成人av免费播放 | 成人免费网站www网站高清 | 亚洲天堂av在线 | 欧美男男videos | 91视频www.| 97天天干 | 在线视频一区二区 | 免费观看毛片 | 一区二区蜜桃 | 日本亚洲欧美 | 日韩中文不卡 | 亚洲成人精 | 日韩视频1| 久久久精品高清 | 国产精品久久久久久久久久99 | 999久久久久久久久6666 | 亚洲一二三区在线观看 | 色偷偷噜噜噜亚洲男人 | 在线播放中文字幕 | 国产精品永久久久久久久www |