轉:http://www.reibang.com/p/d5fca0185e83
Xcode測試
前言
總算在今天把單元測試的官方文檔翻譯寫成了一片博客霞丧。首先感謝黨署鸡,感謝人民额嘿,感謝我的父母交洗。也必須感謝下我們部門的領導給了我一個這樣的時間來做這件事情愧哟。翻譯的不算太好奥吩,很多地方都還只是一個概念,在翻譯的時候存在一些困難蕊梧。而且單元測試也不止于翻譯了這篇官方的文檔霞赫,它應該是一系列的文檔和說明。我會在今年的時間里肥矢,努力去寫出來一個雛形端衰。希望更多的人可以通過這些介紹認識到測試
介紹
使用Xcode測試
Xcode提供的一個功能,可以進行廣泛的軟件測試甘改。主要測試你的項目的健壯性靴迫,減少BUG,讓你的產品更快的分發(fā)和銷售楼誓。按照預期的功能測試玉锌,提高用戶的滿意度。測試可以幫助你更快開發(fā)疟羹、少做無用功主守。
目錄結構
在這份文件中禀倔,你將學習如何使用Xcode包含的測試功能。XCTest框架添加測試的時候自動鏈接上去的参淫。
1.快速啟動救湖,在Xcode5引進XCTest框架開始,配置項目測試的過程已經簡化可以在導航欄自動的測試和運行涎才。
2.性能測試鞋既,Xcode6以及更高的版本讓你能夠跟蹤和衡量基本單位的性能變化。
3.UI測試耍铜,Xcode7增加了對用戶界面的測試能力邑闺。
4.持續(xù)集成和Xcode服務器,Xcode測試可以使用命令腳本來執(zhí)行或配置在Mac上的漫游器自動運行Xcode服務器上執(zhí)行棕兼。
5.現代化陡舅,Xcode中包含轉換一測試的OCUnit測試項目遷移。
前提
你應該熟悉應用程序的設計和編程的概念伴挚。
快速啟動
快速啟動其實就是介紹了測試的組成部分你可以對測試有一個簡單的理解靶衍。
介紹測試的導航欄
當你準備做測試工作的時候,你會經常使用測試的導航欄茎芋。
測試的導航欄目的是緩解你測試代碼的編寫颅眶、管理、運行田弥、審查測試的操作涛酗。你可以點擊導航欄中的圖標,位于show the issue導航和show the debug導航之間皱蹦。當你創(chuàng)建了一些測試的項目你可以在這里看到一個導航視圖煤杀。
圖中的測試導航現實測試包、類和包含在測試項目方法的分層列表沪哺。圖中的項目是一個簡單的計算器項目沈自。計算器使用一個框架實現,你可以在最高層的SampleCalcTests測試包里看到測試的代碼辜妓。
注意:Xcode的測試目標產生后顯示在測試導航里枯途。如果你的測試使用數據文件、圖像等等籍滴,他們可以被添加到所述的測試包酪夷,并且可以在運行的時候訪問一個NSBundle的API。使用+[NSBundle bundleForClass:]確定你獲得正確的包來進行測試孽惰。Xcode的方案控制構建了什么晚岭。方案還控制哪個可用的測試方法用于測試操作需要去執(zhí)行。你可以啟用和控制通過點擊該項目在測試導航的列表中勋功,選擇啟用或者從快捷菜單中禁用坦报。從而啟用或禁用測試包库说、類和方法。
此視圖中的主要測試包是SampleCalcTests片择。SampleCalcTests包括一個測試類潜的,后面包含九個測試方法。運行按鈕在測試項目名稱的右側字管。這是一個非常方便的方法啰挪,所有的測試項目都集中到了這里(如果使用了一些第三方的測試可能有一些不會出現在這里列表當中)。運行以后紅色的X代表測試不通過嘲叔,綠色的對勾代表測試通過亡呵。運行的測試項目是使用斷言來檢測通過或者故障。
單擊列表中的任何測試類或者測試方法打開測試類借跪。測試類和測試方法在gutter都會顯示一個可點擊的測試的標志(可進行單獨的測試)政己。
在測試導航的底部你可以添加一個測試酌壕,也可以通過一些字符串縮小你的查找范圍掏愁。
為你的App添加測試
在Xcode5或者更高的版本你創(chuàng)建應用的時候可以通過勾選測試的按鈕來為項目添加一個測試。當你創(chuàng)建好以后你可以在你的項目里看到一個測試包卵牍、測試和模版測試的方法果港。但是你的項目可能是由比較早的Xcode版本生成的。這里介紹的就是當你項目里預先沒有測試的時候的一些操作糊昙。
創(chuàng)建一個測試Target
打開測試導航辛掠,單擊左下角的加號按鈕,new unit test target释牺。
在彈出框中選擇OS X或者iOS單元測試萝衩,然后單擊下一步,設置相關的信息没咙。
點擊finish猩谊,完成以后點開。包含一個模版測試類和兩個測試方法的模版祭刚。
運行測試牌捷,查看結果
現在你為你的項目添加了一個測試,然后去開發(fā)測試一些有意義的東西涡驮。首先按住鼠標指針移動到SampleCalcTests在測試導航測試類暗甥,然后點擊運行按鈕運行該類中的所有測試方法。結果在方法名稱的右邊捉捅,編輯區(qū)方法名的左邊撤防。
因為模塊測試和性能測試都是空的,所以測試成功了棒口。并沒有失敗的斷言寄月。measureBlock:處單擊左側的“鉆石”會顯示性能測試的結果焰情。
這個面板允許設置性能基線以及編輯基線和最大STDDREV參數。
編輯測試和重新運行
這個實例項目是一個計算器應用程序剥懒,你需要檢查加内舟、減、乘初橘、除算法的正確性验游,以及測試其他計算器功能的操作。測試是在項目中添加和編寫的保檐,你可以測試任何你想要的測試耕蝉。(這就要求你有一個很好的代碼結構來提供測試)
eg:你可以在SampleCalcTests.m中添加實例聲明和引入類。
#import//// Import the application specific header files#import "CalcViewController.h"#import"CalcAppDelegate.h"@interface CalcTests : XCTestCase {// add instance variables to the CalcTests class@privateNSApplicationapp;? CalcAppDelegate? ? appDelegate;? CalcViewController calcViewController;NSViewcalcView;}@end
然后給測試方法的起一個描述性的名稱夜只,如testAddition并添加要實施的方法垒在。
- (void) testAddition{//obtain the app variables for test accessApp = [NSApplication sharedApplication];calcViewController = (CalcViewController)[[NSApplicationsharedApplication] delegate];calcView = calcViewController.view;//perform two addition tests[calcViewControllerpress:[calcViewviewWithTag:6]];// 6[calcViewControllerpress:[calcViewviewWithTag:13]];// +[calcViewControllerpress:[calcViewviewWithTag:2]];// 2[calcViewControllerpress:[calcViewviewWithTag:12]];// =XCTAssertEqualObjects([calcViewController.displayField stringValue],@"8", @"Part 1 failed.");[calcViewControllerpress:[calcViewviewWithTag:13]];// +[calcViewControllerpress:[calcViewviewWithTag:2]];// 2[calcViewControllerpress:[calcViewviewWithTag:12]];// =XCTAssertEqualObjects([calcViewController.displayField stringValue],@"10", @"Part 2 failed.");}
如果你改變了測試的方法,測試導航列表也會做相應的改變扔亥。
編輯完以后可以使用測試導航(或者gutter)來運行testAddition方法场躯。
當一個斷言失敗,在測試導航和gutter會突出顯示旅挤。根據提示信息你可以非常輕易的找到這個錯誤踢关。進行修改之后就能夠運行成功。
使用setUp()和tearDown()方法
Xcode運行一個測試包的時候會走這個測試類中的所有方法粘茄。那這個測試類中如果都需要一個初始化對象签舞,你就要在每一個方法中對這個對象進行初始化,這樣就會造成很多重復的代碼柒瓣。但是XCTest框架提供了兩個實例方法用于測試類的初始化和釋放儒搭。你可以用這兩個實例方法將這些共同調用的方法寫進去。
使用setup和teardown方法非常簡單芙贫。
- (void)setup
{
[super setUp];
// Put setup code here. This method iscalled before the invocation of each test method in the class.
// obtain the app variables for test access
app = [NSApplication sharedApplication];
calcViewController = (CalcViewController)[[NSApplicationsharedApplication] delegate];
calcView = calcViewController.view;
}
Setup方法會在測試方法之前調用搂鲫,所以測試方法可以直接試用初始化過的屬性。
###概要
從這個簡短的快速入門可以看出來屹培,為一個項目添加測試是很簡單的默穴。但是還是有一些注意事項:
1. Xcode中設置了大部分的基本測試配置。當你添加一個新的測試的時候褪秀,Xcode會自動為你添加這些測試方法蓄诽。使用一個單獨的方法進行測試,可以在測試導航中找到媒吗。
2. 測試導航可以讓你輕松的找到編輯測試的方法仑氛,你可以運行,在導航測試或者gutter。測試失敗的時候你可以在gutter中看到失敗的標志锯岖。
3. 單個測試方法可以包括多個斷言介袜,從而導致單一的合格或者不合格的測試結果捏萍。你可以根據需求來做簡單或者復雜的測試合搅。setup和teardown實例方法可以讓你將通用的代碼寫在里邊警绩。
##基礎測試
測試是指檢驗你的應用程序代碼和庫代碼能否成功運行的過程拌滋,用于衡量預期結果。通過執(zhí)行一些操作棚壁,測試可在執(zhí)行一些操作后檢查一個對象的實例變量的狀態(tài)遗淳,以確定你的代碼在受到邊界條件變化時是否會拋出一個特定的異常等锌介。
###定義測試范圍
所有的軟件都是通過很多的單元組合起來的秋麸,也就是說渐排,小的組件合在一起形成較大的、功能更強的高級組件灸蟆,直到符合項目的需求驯耻。良好的測試需要涵蓋該組合的所有功能。其中單元測試通常處理該項目功能級的小組件炒考。而XCTest允許你為任何層次結構的各個級別的組件編寫相應的測試可缚。
測試組件由什么構成完全取決于你自己,可以是一個類中的一個方法票腰,也可以是完成一個基本目的的一組方法城看。例如女气,一個算術運算杏慰,參見蘋果的官方demo。處理tableView的內容間和代碼數據結構中持有列表名稱間的交互有不同的方法炼鞠。每個方法的操作都意味著應用程序功能的組成部分對它的測試缘滥。一個測試組件的行為應該是完全確定的,無論測試成功或者失敗谒主。
把你的應用程序的行為劃分為越多的組件朝扼,就越能有效的測試你的代碼能否滿足參考標準的各種細節(jié),尤其是當項目不斷的迭代更新的時候霎肯。對于很多組件組成的大型項目來說擎颖,你需要運行很多的測試來徹底檢測整個項目。如果可能的話观游,測試應該快速運行搂捧,擔憂一些測試確實很大,所以運行可能會慢一點懂缕。當有一些故障出現的時候允跑,可以運行一些小的測試快速測試,這樣可以輕松診斷和修復問題。
為項目組件設計測試是測試驅動開發(fā)(test-driven-development TDD)的基礎聋丝,也是一種編寫代碼測試之前編寫測試邏輯的編碼方式索烹。這種開發(fā)方法可以讓你在實施之前確定代碼需求和邊界情況。編寫測試后弱睦,開發(fā)旨在通過測試的算法百姓。在代碼通過測試以后,你才有了提高代碼的基礎况木,才有信心在下一次運行這些測試時能鑒定一些預期行為(導致你的產品產生BUG)的變化瓣戚。
甚至在你不使用測試驅動開發(fā)時,測試還可以降低修改代碼引入的BUG數量焦读,從而幫你提高代碼的特性和功能子库。在一款運行的應用程序中進行測試以確保未來的更改不會改變應用的行為。當你修復這些BUG后矗晃,你需要添加測試以確保該BUG已經被修復仑嗅。測試還可以檢測你的代碼,所以有成功和失敗兩種預期张症,以覆蓋所有邊界條件仓技。
注意:為一個沒有考慮到測試的項目添加測試可能會要求重構部分代碼來使測試變得更加簡單∷姿“Writing Testable Code”包含游泳的編寫可測試代碼的簡單指南脖捻。
組件可以包括你的應用程序的各部分之間的交互。由于有些測試可能需要很長時間兆衅,所以你可能希望定期或者只在一臺服務器上運行他們地沮。(你可以組織自己的測試并以多種方式運行它們,以滿足不同的需求)羡亩。
###性能測試
測試的組件可以同時測試功能和記錄性能摩疑。使用XCTest提供的API你可以測量以時間為基準的性能測試,對一個相似的方法或者功能你可以跟蹤性能的提高或者退化畏铆。
為了衡量一個性能測試的成功或者失敗雷袋,測試必須有一個基準用來評估〈蔷樱基線是運行10次以后計算出來的平均時間的性能測試楷怒。如果與基線相差太多的時候為失敗。
注意:當你第一次運行性能測試的時候系統會提示失敗瓦灶,因為第一次運行的時候基線是未知的鸠删。一旦你設定了一個測量準線,XCTest會報告成功或者失敗倚搬,并提示相信的結果信息冶共。
###用戶界面測試
功能測試和性能測試一般都被稱為單元測試,其中的單元是相對于組件和最小的模塊來確定的(大概意思)。單元測試主要是讓相關的組件能夠按照預期的那樣交互捅僵。從設計的角度來看家卖,單元測試是在開發(fā)的時候編寫的滿足你的預期。
用戶通過源代碼進行界面的交互庙楚。界面的交互一般是整合一整個子系統的操作來實現預期的功能上荡。這些很難使用單元測試來進行測試,這種特殊的測試被稱為UI測試馒闷。
UI測試更貼近于用戶的體驗酪捡。你可以編寫模擬事件添加到UI測試中,捕捉這些對象的反應纳账,然后測試正確性和性能和單元測試十分類似逛薇。
###應用程序測試和庫測試
Xcode測試提供兩種測試:應用程序測試和庫測試。
應用程序測試疏虫。應用程序測試可以檢查App的代碼組件永罚,例如蘋果測試的官方demo。你可以利用應用程序來確保你的UI控件保持原有的位置卧秘,并且你的控件和控制器對象能夠和對象模型正確地工作呢袱。
庫測試。庫測試可檢查獨立代碼(不再應用程序中運行的代碼)的行為是否正確翅敌。利用庫測試羞福,你可以將整個庫的組件放在一起,通常是測試庫的對象和方法蚯涮。你也可以使用庫測試來執(zhí)行代碼的壓力測試治专,以確保它在極端的情況下也能正確執(zhí)行(不大可能出現在一個運行的app中)。這些測試可以幫助你生成一個“健壯的”代碼恋昼,即使在沒有預料的情況下也能運行正常看靠。
###XCTest-Xcode測試框架
XCTest是一個Xcode5及以上版本中使用的測試框架。如果你以前使用過Xcode OCUnit測試液肌,你可能會發(fā)現XCTest和OCUnit有些相似。XCTest是OCUnit更現代化的替代鸥滨,可以更好的與Xcode集成嗦哆,為將來Xcode測試功能的改進奠定了基礎。Xcode把XCTest.framework并入你的項目婿滓,而不是SenTesting.framework老速。該框架提供可以讓你設計測試并在代碼中運行的API。
注意:Xcode包括一個遷移助手凸主,可用來轉換包含OCUnit測試的項目橘券。更多OCUnit想XCTest轉換的詳細信息,請參閱“Transitioning frome OCUnit to XCTest”
###測試從哪里運行
當你開始創(chuàng)建測試的時候,記住下面的方法:
1. 專注于測試你的代碼的最基礎的功能旁舰、模型類锋华、方法,它們與控制器相交互箭窜。
應用程序的高級框圖很可能會包含Model毯焕、View和Controller類別,對于每個使用Cocoa和Cocoa Touch的開發(fā)者來說磺樱,這是一個熟悉設計模式纳猫。當你編寫要覆蓋所有Model類別的測試時,你必須要知道App的基礎已經進行了良好的測試竹捉,而且要編寫Controller Classes測試之前芜辕,它將帶你接觸你的應用程序更復雜的部分。
2. 作為一個可選的起始點块差,如果你正在編寫一個框架或庫物遇,你可能想從App接口開始。從那里你可以按照你的方式進入內部類憾儒。
##編寫測試類與方法
但你使用測試導航面板往項目中添加測試target的時候询兴,Xcode會在測試導航面板里展示除測試類和測試方法。在測試target里是包含測試方法的測試類起趾。
###測試target诗舰、測試包、測試導航
在學習創(chuàng)建測試類前训裆,有必要看看測試導航面板眶根。它對創(chuàng)建和運行測試工作極為重要。
測試導航面板羅列了測試包里的所有組件內容边琉,并在一個層次列表里展示出測試類和測試方法属百。下邊是一個工程的測試導航面板視圖,包含了多個測試目標变姨,展示了測試包族扰、測試類、以及測試方法的嵌套層級定欧。
測試包里可以包含多個測試類渔呵。你可以使用測試類把測試分到相關的組群里,或者按照功能分砍鸠,或者按照組織目的分扩氢。例如蘋果測試的官方demo,創(chuàng)建了BasicFunctionsTests爷辱、AdvancedFunctionsTests录豺、DisplayTests classes三個類朦肘,但它們都屬于Mac_Calc_Tests測試包。
一些測試類型可能會共享某些類型的setup和teardown双饥,把這些測試整合到類里邊會更加合理媒抠,這樣可以最小化每個測試方法所需的編寫代碼。
###創(chuàng)建測試
可以使用加號按鈕在導航測試面板中選中“New Test Class”命令來創(chuàng)建新測試類兢哭。
基于你在配置頁面鍵入的測試類名领舰,你添加的每一個類都會使得一個名為TestClassName.m的文件被添加到項目中。
注意:所有的測試類都是XCTest框架XCTestCase類的子類迟螺。
盡管Xcode會默認的把測試類添加到工程測試項目所創(chuàng)建的組中冲秽,你還是可以在項目中組織自己選擇的文件。當你按下Next按鈕矩父,標準的Xcode添加文件頁面如下所示:
你可以使用相同的方法在工程導航面板中添加文件锉桑。具體使用當法詳見“Adding an Existing File or Folder”。
注意:當你用Xcode5及以上版本創(chuàng)建工程時窍株,一個測試target和相關的測試包都會被默認的創(chuàng)建民轴,名稱根據工程名獲得。比如創(chuàng)建名為MyApp的項目球订,則會自動生成一個名為MyAppTests的測試包后裸,以及一個名為MyAppTests的測試類,關聯在MyAppTests.m實例文件中冒滩。
###測試類的結構
測試類包含以下的基礎結構:
#import
@interface SampleCalcTests : XCTestCase
@end
@implementation SampleCalcTests
- (void)setUp {
[super setUp];
// Put setup code here. Thismethod is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. Thismethod is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of afunctional test case.
// Use XCTAssert and relatedfunctions to verify your tests produce the correct results.
}
- (void)testPerformanceExample {
// This is an example of aperformance test case.
[self measureBlock:^{
// Put the code you want tomeasure the time of here.
}];
}
@end
測試類用Objective-C實現微驶。注意實現里包含了方法,比如setup和teardown的基本實例方法开睡。這些方法是必須的因苹。如果類中的所有的測試方法都需要相同的代碼,你可以定制setup和teardown來包含這些代碼篇恒。你添加的代碼在每一個測試方法的之前和之后調用扶檐。你可以選擇添加定制的設置(+ (void)setUp)和卸載teardown(+ (void)tearDown)方法,它們在類里所有的測試方法的之前和之后調用胁艰。Xcode執(zhí)行測試可以明確這些方法的使用款筑。
測試執(zhí)行的流程
在執(zhí)行測試的過程中,XCTest找到所有集成與XCTestCase(它是測試類)的類蝗茁,為每一個類運行它們的測試方法醋虏。對于每個類來說,測試開始于運行類的setup方法哮翘。對于每個測試方法來說,一個新的類實例被創(chuàng)建毛秘,他的實例setup方法就會執(zhí)行饭寺。在跑完測試方法之后阻课,實例teardown方法。類中這樣連續(xù)重復執(zhí)行所有的測試方法艰匙。在運行了teardown最后的測試方法后限煞,Xcode會執(zhí)行類teardown方法,并開始下一個類员凝。這種序列已知重復直到跑完所有測試類的所有測試方法署驻。
編寫測試方法
你通過編寫測試方法把測試寫到測試類中,一個測試方法是以test開頭的測試類的實例方法健霹,沒有參數旺上,返回void,比如TestColorsRed測試方法調用工程中的代碼糖埋,如果代碼沒有產生預期的效果宣吱,那么會用一系列的斷言API報錯。比如瞳别,一個函數返回值可能于預期相比不同征候,或者你的測試方法使用了某個不適當的方法都將會拋出異常∷盍玻“XCTest Assertions”描述了這些情況疤坝。為了是測試方法能夠正常訪問被測代碼,引入正確的頭文件到測試類中很重要馆铁。當Xcode運行測試時跑揉,它調用的每個測試方法都是獨立的。因此每個方法需要準備和清理輔助變量叼架、結構以及與主題API進行交互的對象等畔裕。如果類中所有的測試方法的代碼是相同的,你可以直接把它添加到必走的setup和teardown的實例方法中乖订,詳見“TestClassStructure”扮饶。
下邊是一個測試方法的模型:
- (void)testColorIsRed {? //Setup, call test subjectAPI. (CodecouldbesharedinsetUpmethod.)? //Testlogicandvalues, assertions reportpass/fail to testing framework.? //Teardown. (Codecould besharedintearDownmethod.}
這里有一個簡單的測試方法例子,檢查是否成功為SampleCalc創(chuàng)建了CalcView實例乍构,詳見“快速啟動”甜无。
- (void) testCalcView {
// setup
app = [NSApplication sharedApplication];
calcViewController =(CalcViewController)[NSApplication sharedApplication] delegate];
calcView = calcViewController.view;
XCTAssertNotNil(calcView, @"Cannot findCalcView instance");
// no teardown needed
}*
編寫異步操作測試
測試是同步的,因為只有當上一次測試結束以后才進行下一個測試哥遮。但是越來越多的代碼使用異步執(zhí)行岂丘。為了處理這些異步調用執(zhí)行的方法和功能組件,Xcode6增強了包括序列化異步執(zhí)行測試方法的能力眠饮,等待異步回調或者超時完成奥帘。
例如:
// Test that the documentis opened. Because opening is asynchronous,// use XCTestCase'sasynchronous APIs to wait until the document has// finished opening.-(void)testDocumentOpening{// Create anexpectation object.// This test only has one, but it'spossible to wait on multiple expectations.XCTestExpectationdocumentOpenExpectation = [selfexpectationWithDescription:@"document open"];NSURLURL =[[NSBundlebundleForClass:[selfclass]]? ? ? ? ? ? ? ? ? ? ? ? ? ? URLForResource:@"TestDocument"withExtension:@"mydoc"];UIDocumentdoc= [[UIDocumentalloc] initWithFileURL:URL];? ? [docopenWithCompletionHandler:^(BOOLsuccess) {XCTAssert(success);// Possibly assert other things here about the document after it hasopened...// Fulfill the expectation-this will cause -waitForExpectation// to invoke its completion handler andthen return.[documentOpenExpectation fulfill];? ? }];// The testwill pause here, running the run loop, until the timeout is hit// or all expectations are fulfilled.[selfwaitForExpectationsWithTimeout:1handler:^(NSErrorerror) {? ? ? [doc closeWithCompletionHandler:nil];? ? }];}
有關更多異步操作的相信信息,請參閱“XCTest.framework”下的XCTestCase+AsynchronousTesting.h文件仪召。
性能測試
性能測試就是在代碼塊中運行10次寨蹋,收集平均執(zhí)行時間和和標準的偏差松蒜。這些值形成一個平均值,用來評估和基線對比的成功或者失敗已旧。**注意:基線是您指定要用于檢測合格與否的瓶價值秸苗。該報告的UI提供了一種機制來設置或者更改基準值。**為了實現性能測試运褪,在Xcode6以后當中使用新的XCTest方法的API惊楼。
- (void)testPerformanceExample{// This is an example of a performance testcase.[selfmeasureBlock:^{// Put the code you want to measure thetime of here.}];}
下面的例子簡單的演示了一個用計算器應用程序編寫的性能測試的測試速度。一個measureBlock隨著時間的增加XCTest迭代秸讹。
- (void) testAdditionPerformance{
[self measureBlock:^{
// set the initial state
[calcViewController press:[calcViewviewWithTag: 6]];? // 6
// iterate for 100000 cycles of adding2
for (int i=0; i<100000; i++) {
[calcViewController press:[calcViewviewWithTag:13]];? // +
[calcViewController press:[calcViewviewWithTag: 2]];? // 2
[calcViewController press:[calcViewviewWithTag:12]];? // =
}
}];
}
運行一次性能測試檀咙,在測試導航面板的導航器中提供信息。點擊該信息會顯示運行出來的值嗦枢。結果顯示包括控制設置的結果作為準線和未來的測試做對比攀芯。基線存儲了每個設備的配置文虏,所以你相同的測試在不同的設備上執(zhí)行侣诺,會有不同的準線。(取決于配置的處理速度氧秘,內存等等)
注意:性能測試總是在第一次運行年鸳,直到準線被設置在一個特定的設備配置中報告失敗。
有關性能測試的更多詳細的信息丸相,請參閱XCTest.framework下的XCTestCase.h文件搔确。
編寫UI測試
創(chuàng)建XCTest UI測試是單元測試的一個擴展對于相同的編程模型。參見“UserInterfaceTesting”灭忠。
編寫swift測試
swift控制器和模型不能訪問程序內部和框架內部聲明膳算。在Xcode6訪問swift的內部功能,你需要進入公共的切入點來進行測試弛作,降低了swift的安全特性涕蜂。Xcode7提供了這個問題的解決方案:
swift內部訪問時,測試通過通知編輯器生成進行訪問映琳。編譯器通過一個新的控制-enable進行更改机隙,Xcode在接受到這個通知的時候生成。這種行為是控的萨西,對新的項目的默認設置來進行設置有鹿。他不需要改變源代碼。
通過修改導入頭文件的聲明谎脯,來改變測試入口的可見性葱跋。使用新的@testable屬性導入,改變你的測試代碼源梭,不需要修改應用代碼年局。
importCocoa@NSApplicationMainclassAppDelegate:NSObject,NSApplicationDelegate{@IBOutletweakvarwindow:NSWindow!funcfoo(){println("Hello,World!")}}
編寫一個測試類际看,允許訪問Appdelegate類咸产,修改導入的語句與你的測試代碼使用@testable屬性
// Importing XCTestbecause of XCTestCaseimportXCTest// Importing AppKitbecause of NSApplicationimportAppKit// Importing MySwiftAppbecause of AppDelegate@testableimportMySwiftAppclassMySwiftAppTests:XCTestCase{functestExample(){
letappDelegate =NSApplication.sharedApplication().delegateas! AppDelegate
*
appDelegate.foo()
}
}
有了這個解決方案矢否,你的swift內部代碼能夠完全的被測試方法訪問到。
XCTest斷言
你的測試方法使用XCTest框架提供給的斷言來展示Xcode的測試結果脑溢。所有的斷言都有一個類似的形式:項目比較或邏輯表達僵朗,一個失敗的結果字符串格式,和插入到字符串格式中的參數屑彻。
注意:所有的斷言最后一個參數是format…验庙,格式字符串和變量參數列表。XCTest為所有斷言提供了默認的失敗結果字符串社牲,可以使用參數傳遞到斷言里粪薛。Format字符串提供了可選的額外的失敗自定義描述,就可以進一步選擇提供的描述搏恤。這個參數是可選的违寿,也可以完全忽略。
例如:
XCTAssertEqualObjects([calcViewController.displayField stringValue], @"8", @"Part 1 failed.");
這段簡單明了的描述是說:“Indicate a failure when a string created from the value of the controller’s display field is not the same as the reference string ‘8’”熟空。如果斷言失敗那么Xcode在測試導航面板發(fā)出失敗信號藤巢,然后Xcode會在issues導航面板、源碼編輯器以及其他地方展示失敗的描述息罗。下面是源代碼編輯器典型的斷言結果:
測試方法可以包含多個斷言掂咒,如果任何斷言包含失敗報告,那么Xcode都會發(fā)出測試失敗信號迈喉。
斷言氛圍物種類型:無條件報錯绍刮、等價測試、nil測試挨摸、布爾測試以及異常測試孩革。
用類別區(qū)分斷言
下面的區(qū)域列出了XCTest斷言。你可以XCTestAssertions.h中獲取更多斷言的信息油坝。
無條件報錯
XCTFail生成一個無條件的報錯
XCTFail(format...)
等價測試
XCTAssertEqualObjectes嫉戚,當expresson1不等于expresson2時報錯(或者一個對象為空,另一個對象不為空)
XCTAssertEqualObjects(expression1, expression2, format...)
XCTAssertNotEqualObjects. 當expression1等于expression2時報錯澈圈。
XCTAssertNotEqualObjects(expression1, expression2, format...)
XCTAssertEqual. 當expression1不等于expression2時報錯金吗,這個測試用于C語言的標量。
XCTAssertEqual(expression1, expression2, format...)
XCTAssertNotEqual. 當expression1等于expression2時報錯擒悬,這個測試用于C語言的標量榕茧。
XCTAssertNotEqual(expression1, expression2, format...)
XCTAssertEqualWithAccuracy. 當expression1和expression2之間的差別高于accuracy 將報錯。這種測試適用于floats和doubles這些標量诽偷,兩者之間的細微差異導致它們不完全相等坤学,但是對所有的標量都有效疯坤。
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)
XCTAssertNotEqualWithAccuracy. 當expression1和expression2之間的差別低于accuracy將產生失敗。這種測試適用于floats和doubles這些標量深浮,兩者之間的細微差異導致它們不完全相等压怠,但是對所有的標量都有效。
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)
Nil(空)測試
XCTAssertNil. 當expression參數非nil時報錯飞苇。
XCTAssertNil(expression, format...)
XCTAssertNotNil. 當expression參數為nil時報錯菌瘫。
XCTAssertNotNil(expression, format...)
Boolean測試
XCTAssertTrue. 當expression計算結果為false時報錯。
XCTAssertTrue(expression, format...)
XCTAssert. 當expression計算結果為false時報錯布卡,與XCTAssertTrue同義雨让。
XCTAssert(expression, format...)
XCTAssertFalse. 當expression計算結果為true報錯。
XCTAssertFalse(expression, format...)
異常測試
XCTAssertThrows.當expression不拋出異常時報錯忿等。
XCTAssertThrows(expression, format...)
XCTAssertThrowsSpecific.當expression針對指定類不拋出異常時報錯栖忠。
XCTAssertThrowsSpecific(expression, exception_class, format...)
XCTAssertThrowsSpecificNamed. 當expression針對特定類和特定名字不拋出異常時報錯。對于AppKit框架或Foundation框架非常有用贸街,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)庵寞。
XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, format...)
XCTAssertNoThrow. 當expression拋出異常時報錯。
XCTAssertNoThrow(expression, format...)
XCTAssertNoThrowSpecific. 當expression針對指定類拋出異常時報錯匾浪。任意其他異常都可以皇帮;也就是說它不會報錯。
XCTAssertNoThrowSpecific(expression, exception_class, format...)
XCTAssertNoThrowSpecificNamed. 當expression針對特定類和特定名字拋出異常時報錯蛋辈。對于AppKit框架或Foundation框架非常有用属拾,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)
XCTAssertNoThrowSpecificNamed(expression, exception_class, exception_name, format...)
運行測試并查看結果
使用Xcode測試導航面板,可以很容易的運行測試并查看結果冷溶。有另外幾種運行測試的交互方法渐白。Xcode運行測試取決于一個scheme中開啟了哪些testtarget。測試導航面板讓你無需使用scheme編輯器就能直接控制那些被包含逞频、被開啟或關閉的testtarget纯衍、類以及方法。
運行測試命令
測試導航面板提供了快捷的方法苗胀,以將運行測試作為編碼流程的一部分襟诸。測試同樣可以直接在源代碼編輯器里運行或者使用product菜單運行。
使用測試導航面板
在測試導航面板中基协,將鼠標停在測試包歌亲、類或方法名上時,會出現一個“Run”按鈕澜驮。你可以運行某個特定測試陷揪,也可以運行一個類中的測試或運行一個測試包中的所有測試,這取決于列表中的鼠標停留位置。
將鼠標懸停在測試包名上悍缠,并點擊右邊出現的運行按鈕來測試一個包中的所有測試卦绣。
將鼠標懸停在類名上,并點擊右邊出現的運行按鈕來測試一個類中的所有測試飞蚓。
將鼠標巡艇在測試方法名上滤港,并點擊右側出現的運行按鈕來測試一個單獨的測試。
使用源代碼編輯器
當在源代碼編輯器中打開一個測試類玷坠,每個測試方法名字旁的邊欄會明顯的指示器蜗搔。在指示器上懸停鼠標,出現一個運行按鈕八堡。點擊按鈕運行該測試方法,指示器隨后顯示該測試成功或失敗的狀態(tài)聘芜。再次將鼠標懸停到指示器上可以再次顯示運行按鈕來重復測試兄渺。這種機制一次只運行一個測試。
注意:出現在@implementation旁邊的指示器同樣也適用于類汰现,允許你運行類中所有的測試挂谍。
使用Product菜單
Product菜單包括了從鍵盤直接運行測試的快捷命令。
Product>Test運行當前激活的方案(scheme)瞎饲。鍵盤快捷鍵是Conmmand-U口叙。
Product>Build for>Testing和Product>Perform Action>Test without Building。這兩個命令可以用來構建測試并運行獨立于其他的測試嗅战。這是簡化構建和測試進程的快捷命令妄田。對于修改了代碼并在構建過程中檢查警告或錯誤時,這是特別游泳的驮捍,或者如果你知道當前的構建是最新的疟呐,他也可以加速測試過程。鍵盤快捷方式分別是Shift-Command-U和Control-Command-U东且。
Product>Perform Action>Test启具。當你編輯一個測試方法時,這個動態(tài)菜單選項展示當前光標所處的測試方法珊泳,并允許你使用鍵盤快捷鍵方式來運行測試鲁冯。命令的名稱取決于將要運行的測試,比如Product>Perform Action>Test testAddition色查∈硌荩快捷鍵Control-Opention-Command-U。
注意:除了源代碼編輯器综慎,該命令還基于工程導航面板中的選擇情況運行涣仿。當人和一個導航面板處于激活狀態(tài),源代碼編輯器就是去了焦點,并且該命令將使用任何一個導航面板中的當前選擇作為輸入好港。在測試導航面板中愉镰,可以選擇測試包、類钧汹、或方法丈探。在工程導航面板中,可以選擇測試類實現文件拔莱,例如CalcTests.m碗降。
Product>Perform Action>Test Again。當測試方法在調試/編輯代碼中暴露出問題時塘秦,返回最后一個被執(zhí)行的測試方法非常有用讼渊。像Product>Perform Action>Test命令,運行的測試名稱在命令中出現尊剔,例如Product>Perform Action>Test Again testAddition爪幻。鍵盤的快捷方式Control-Option-Command-G。
顯示測試結果
XCTest框架有幾種不同的方式在Xcode中展示測試結果须误。下面的屏幕截圖展示了在哪里查看這些測試結果.
在一個或一組測試運行后挨稿,你可以在測試導航面板中瀏覽測試通過或者失敗.
如果測試方法被疊加到各自的類中,或測試方法被折疊到測試包中京痢,該標識則反映了封閉測試的集合狀態(tài)奶甘,表明在這個類或者包中至少有一個測試方法不通過。
在源代碼編輯器中祭椰,你可以瀏覽測試通過或者失敗的標識和調試信息
在報告導航面板中臭家,可以通過測試運行結果查看。
對于一個性能測試吭产,單擊時間列中的值侣监,獲得性能測試的詳細報告。你可以通過單擊各個測試運行按鈕臣淤,查看10次運行的詳細信息橄霉。編輯按鈕可以修改基線和允許通過或者失敗的最大標準偏差。
日志導航面板中邑蒋,你可以瀏覽相關的錯誤描述和其他一些輸出摘要姓蜂。點擊走遍的提示箭頭標識,可以展開所有的測試運行細節(jié)医吊。
注意:出了左邊展開的三角圖標钱慢,測試失敗項右邊的小圖標可以展開顯示更多信息。
調試控制臺以文本形式展示了測試運行的綜合信息卿堂。這些信息和日志導航面板中顯示的信息一樣束莫。但如果你已經處于debug狀態(tài)懒棉,那么debug的輸出也會出現在這里。
使用Schemes(方案)和Test Target(測試目標)
XcodeScheme控制著構建览绿、運行策严、測試和調試這些菜單命令的行為。當創(chuàng)建TestTarget并使用測試導航面板執(zhí)行其他測試系統操作時饿敲,Xcode5為我們管理Scheme配置——例如妻导,當你開啟或者關閉一個測試方法、測試類或測試包時怀各。使用Xcode Server和持續(xù)集成需要通過設置Manager Schemes頁面中的復選框來將一個Scheme設置稱共享倔韭,并將其連同你的工程和源代碼導出到一個源文件倉庫。
Scheme配置方法如下:
選擇Scheme menu >Manage Scheme瓢对,彈出管理頁寿酌。
這個工程中有兩個Scheme,一個用來構建應用沥曹,一個用來構建框架/庫份名。右側的Share復選框用來將Scheme配置為共享,并允許Xcode Server bots使用妓美。
在管理頁中,雙擊一個Scheme鲤孵,顯示Scheme Editor壶栋。一個Scheme的測試行為標識了你執(zhí)行測試命令時Xcode執(zhí)行的測試。
注意:測試目標普监、測試類和測試方法所關聯的測試導航面板和配置/設置助手通常維護所有關于測試操作的Scheme設置贵试。
關于使用、配置和編輯Scheme的更多信息可以查看Scheme Configuration Help凯正,或者視頻WWDC 2012:Working with Scheme and Projects in Xcode毙玻。
構建測試-測試應用、測試庫
應用程序在你的應用的上下文中運行廊散,允許你創(chuàng)建測試桑滩,這些測試結合了不同的類、庫/框架和應用功能的角度的行為允睹。庫測試獨立于你的應用运准,在一個庫或框架中采用實驗類和方法,來驗證它們的行為符合庫的明確要求缭受。兩種類型的測試包需要不同的構建設置胁澳。在新的target助手中通過選擇目標參數來創(chuàng)建testtarget時,會執(zhí)行構建設置配置米者。目標助手隨著目標下拉菜單顯示韭畸。名為SampleCalc的應用和名為CalcLibrary的庫可供選擇宇智。
選擇SampleCalc作為該測試目標所關聯的構建產品配置構建設置來測試一個應用。測試的執(zhí)行基于應用進程胰丁,測試在得到SampleCalc你可以根據自己的偏好改變它随橘。
如果你選擇CalcLibrary作為關聯的構建產品,目標助手將會在配置構建設置來測試庫隘马。Xcode引導測試運行時上下文和框架/庫太防,以及你的測試代碼-基于一個Xcode管理的進程。這種情況下默認的產品名字來自于庫目標(“CalcLibrary Tests”)酸员。同樣你可以基于自己的喜好更改蜒车。
默認構建設置
大多數情況下,配置構建設置來測試應用或庫所要做的唯一一件事就是選擇正確的測試目標幔嗦。Xcode則自動關注構建設置管理酿愧。因為你可能有一個需要復雜構建設置的功能,所以了解Xcode為應用測試和庫測試所建立的標準是非常有用的邀泉。
在這里使用官方的測試demo來演示:
在工程導航面板中單擊SampleCalc進入工程編輯器嬉挡,然后選擇SampleCalc Tests應用測試目標。在編輯器的General面板中汇恤,有一個目標快捷菜單庞钢。該下拉菜單應當展示SampleCalc為目標。
你可以檢查該構建設置是否正確因谎。
點擊構建設置基括,在搜索框中輸入Bundle Loader。針對SampleCalc的應用測試被SampleCalc App加載财岔。你可以看到針對Debug和Release的作為自定義參數的可執(zhí)行文件路徑风皿。搜索Test Host也可以看到相同的路徑。
該工程的庫目標名為CalcLibrary匠璧,并且已經與名為CalcLibraryTests的測試目標關聯桐款。
選擇CalcLibraryTests目標并查看General面板。CalcLibrary被作為目標夷恍。
像應用測試目標一樣魔眨,你可以使用build Settings面板查看Bundle Loader和Test Host構建設置,下圖展示Bundle Loader搜索設置裁厅。
在庫測試目標的案例中冰沙,Bundle Loader和Test Host項目都沒有關聯的參數。這表明Xcode已經默認正確配置了它們执虹。
測試的目的
應用測試在OS X拓挥,iOS(真機)和iOS模擬器上運行。庫測試運行在OS X和iOS模擬器上袋励。XcodeServer可以通過是黨的配置源代碼倉庫侥啤,共享Scheme和bot在運行OS XServer的Mac上運行当叭。更多關于XcodeServer運行目標的信息,請查看“Automating the TestProcesswith Continuous Integration”盖灸。
調試測試
所有標準的Xcode調試工具在執(zhí)行測試的時候都可以使用蚁鳖。
測試調試工作流
要確定的第一件事情就是:造成測試失敗的原因是測試中的代碼有BUG還是執(zhí)行的測試方法存在BUG。測試失敗可以指出一些不同類型的問題赁炎,即有你的假設醉箕,在測試中的代碼需求,也有測試代碼本身徙垫,所以調試測試可以橫跨幾個不同的工作流讥裤。然而通常你的測試方法是相對較小和直接的,所以最好首先檢查測試的目的是什么姻报,以及它是如何實現的己英。
值得注意的一些常見的問題:
測試邏輯是否正確?實現是否正確吴旋?測試方法用作比較基礎使用的字面值损肛,檢查它們的筆誤和粗舞始終是個好主意。
假設是什么荣瑟?例如治拿,你可能在測試方法里使用了錯誤的數據類型,創(chuàng)建了一個你所測試的代碼的范圍錯誤笆焰。
是否使用了正確的斷言來報告忍啤,“通過/失敗”狀態(tài)?例如仙辟,可能測試的狀態(tài)需要XCTAssertTure而不是XCTAsserFalse。有時候很容易造成這些錯誤鳄梅。
假設你的測試假設是正確的叠国,并且測試方法也正確,那么錯誤一定在要測試的代碼中〈魇現在定位并修復它粟焊。
具體的測試調試工具
Xcode有幾個工具專門用來在你測試時定位和調試代碼。
測試失敗斷點
在斷電導航面板中(BreakPoint Navigator)孙蒙,點擊Add(加號)按鈕项棠,選擇Add Test Failure breakpoint設置一個特殊的斷點。
當測試方法觸發(fā)了失敗斷言挎峦,這個斷點會終止測試的運行香追。在測試代碼發(fā)生錯誤點擊后立馬停止運行,可以讓你快速的找到問題發(fā)生的位置坦胶。你可以看看testAddition測試方法透典,通過為錯誤字符串設置用來比較的參考標準晴楔,比較字符串被強行斷言為失敗。測試失敗斷點檢測該失敗斷言并停止了該點測試的執(zhí)行峭咒。
當測試終端税弃,你也就停止了測試的執(zhí)行。然后在斷言前設置一個常規(guī)的斷點凑队,再次運行測試(為了簡單期間则果,你可以在源代碼編輯器側欄中點擊“Run”按鈕來運行該測試),并繼續(xù)調試操作來修復問題漩氨。
使用工程菜單命令運行測試
調試測試方法時西壮,最好記住菜單命令Project>Perform Action>Test Again和Project>Perform Action>Test。如果你正在測試失敗發(fā)生后編輯修復代碼才菠,或運行你正在編寫的測試方法茸时,它們提供了一個便捷的方式來測試最后一個方法。更多信息請查看“Using the Product menu”赋访。
當然你也可以始終使用測試導航面板或源代碼編輯器側邊欄中的“Run”按鈕來運行測試可都,都很方便。
輔助編輯器類別
輔助編輯器分類中增加了兩個專門的分類來運行特殊的測試蚓耽。
Test Callers category渠牲。如果你修復了一個飲用測試失敗的方法,你可能會想要檢查該方法在其他測試中是否被調用并運行成功步悠。帶著這個問題签杈,在源代碼編輯器中打開輔助編輯器,并從菜單中選擇Test Classes分類鼎兽。你可以從下拉菜單定位到任何調用它的測試方法的位置答姥,這樣你就可以運行它們,以確保你的修復沒有造成其他的問題谚咬。
Test Classes Category鹦付。該分類和Test Callers類似,不過顯示的是包含測試方法的類列表择卦,這些方法與主源碼編輯器中編輯類的相關敲长。對于增加測試來說,是一個非常好的機會秉继,例如給還沒有被并入測試方法中的新方法增加測試祈噪。
測試時的異常斷點
通常當異常被異常斷點捕獲時就會終止測試執(zhí)行,所以測試運行時通常都會關閉異常斷點以避免不適當的定位拋出的斷點尚辑。當你尋找一個特定的問題并想終止測試來修復它時可以打開異常斷點辑鲤。