Xcode測試
前言
????總算在今天把單元測試的官方文檔翻譯寫成了一片博客悲关。首先感謝黨胆绊,感謝人民间影,感謝我的父母欲低。也必須感謝下我們部門的領(lǐng)導(dǎo)給了我一個(gè)這樣的時(shí)間來做這件事情辕宏。翻譯的不算太好,很多地方都還只是一個(gè)概念砾莱,在翻譯的時(shí)候存在一些困難瑞筐。而且單元測試也不止于翻譯了這篇官方的文檔,它應(yīng)該是一系列的文檔和說明腊瑟。我會在今年的時(shí)間里聚假,努力去寫出來一個(gè)雛形。希望更多的人可以通過這些介紹認(rèn)識到測試闰非。
介紹
使用Xcode測試
Xcode提供的一個(gè)功能膘格,可以進(jìn)行廣泛的軟件測試。主要測試你的項(xiàng)目的健壯性财松,減少BUG瘪贱,讓你的產(chǎn)品更快的分發(fā)和銷售。按照預(yù)期的功能測試辆毡,提高用戶的滿意度菜秦。測試可以幫助你更快開發(fā)、少做無用功舶掖。
目錄結(jié)構(gòu)
在這份文件中球昨,你將學(xué)習(xí)如何使用Xcode包含的測試功能。XCTest框架添加測試的時(shí)候自動(dòng)鏈接上去的眨攘。
- 1.快速啟動(dòng)主慰,在Xcode5引進(jìn)XCTest框架開始,配置項(xiàng)目測試的過程已經(jīng)簡化可以在導(dǎo)航欄自動(dòng)的測試和運(yùn)行鲫售。
- 2.性能測試共螺,Xcode6以及更高的版本讓你能夠跟蹤和衡量基本單位的性能變化。
- 3.UI測試情竹,Xcode7增加了對用戶界面的測試能力藐不。
- 4.持續(xù)集成和Xcode服務(wù)器,Xcode測試可以使用命令腳本來執(zhí)行或配置在Mac上的漫游器自動(dòng)運(yùn)行Xcode服務(wù)器上執(zhí)行鲤妥。
- 5.現(xiàn)代化佳吞,Xcode中包含轉(zhuǎn)換一測試的OCUnit測試項(xiàng)目遷移。
前提
你應(yīng)該熟悉應(yīng)用程序的設(shè)計(jì)和編程的概念棉安。
快速啟動(dòng)
快速啟動(dòng)其實(shí)就是介紹了測試的組成部分你可以對測試有一個(gè)簡單的理解底扳。
介紹測試的導(dǎo)航欄
當(dāng)你準(zhǔn)備做測試工作的時(shí)候,你會經(jīng)常使用測試的導(dǎo)航欄贡耽。
測試的導(dǎo)航欄目的是緩解你測試代碼的編寫衷模、管理鹊汛、運(yùn)行、審查測試的操作阱冶。你可以點(diǎn)擊導(dǎo)航欄中的圖標(biāo)刁憋,位于show the issue導(dǎo)航和show the debug導(dǎo)航之間。當(dāng)你創(chuàng)建了一些測試的項(xiàng)目你可以在這里看到一個(gè)導(dǎo)航視圖木蹬。
圖中的測試導(dǎo)航現(xiàn)實(shí)測試包至耻、類和包含在測試項(xiàng)目方法的分層列表。圖中的項(xiàng)目是一個(gè)簡單的計(jì)算器項(xiàng)目镊叁。計(jì)算器使用一個(gè)框架實(shí)現(xiàn)尘颓,你可以在最高層的SampleCalcTests測試包里看到測試的代碼。
注意:Xcode的測試目標(biāo)產(chǎn)生后顯示在測試導(dǎo)航里晦譬。如果你的測試使用數(shù)據(jù)文件疤苹、圖像等等,他們可以被添加到所述的測試包敛腌,并且可以在運(yùn)行的時(shí)候訪問一個(gè)NSBundle的API卧土。使用+[NSBundle bundleForClass:]確定你獲得正確的包來進(jìn)行測試盈匾。Xcode的方案控制構(gòu)建了什么娄昆。方案還控制哪個(gè)可用的測試方法用于測試操作需要去執(zhí)行。你可以啟用和控制通過點(diǎn)擊該項(xiàng)目在測試導(dǎo)航的列表中损肛,選擇啟用或者從快捷菜單中禁用凶硅。從而啟用或禁用測試包缝裁、類和方法扫皱。
此視圖中的主要測試包是SampleCalcTests足绅。SampleCalcTests包括一個(gè)測試類,后面包含九個(gè)測試方法韩脑。運(yùn)行按鈕在測試項(xiàng)目名稱的右側(cè)氢妈。這是一個(gè)非常方便的方法,所有的測試項(xiàng)目都集中到了這里(如果使用了一些第三方的測試可能有一些不會出現(xiàn)在這里列表當(dāng)中)段多。運(yùn)行以后紅色的X代表測試不通過首量,綠色的對勾代表測試通過。運(yùn)行的測試項(xiàng)目是使用斷言來檢測通過或者故障进苍。
單擊列表中的任何測試類或者測試方法打開測試類加缘。測試類和測試方法在gutter都會顯示一個(gè)可點(diǎn)擊的測試的標(biāo)志(可進(jìn)行單獨(dú)的測試)。
在測試導(dǎo)航的底部你可以添加一個(gè)測試觉啊,也可以通過一些字符串縮小你的查找范圍拣宏。
為你的App添加測試
在Xcode5或者更高的版本你創(chuàng)建應(yīng)用的時(shí)候可以通過勾選測試的按鈕來為項(xiàng)目添加一個(gè)測試。當(dāng)你創(chuàng)建好以后你可以在你的項(xiàng)目里看到一個(gè)測試包杠人、測試和模版測試的方法勋乾。但是你的項(xiàng)目可能是由比較早的Xcode版本生成的宋下。這里介紹的就是當(dāng)你項(xiàng)目里預(yù)先沒有測試的時(shí)候的一些操作。
創(chuàng)建一個(gè)測試Target
打開測試導(dǎo)航辑莫,單擊左下角的加號按鈕学歧,new unit test target。
在彈出框中選擇OS X或者iOS單元測試各吨,然后單擊下一步枝笨,設(shè)置相關(guān)的信息。
點(diǎn)擊finish揭蜒,完成以后點(diǎn)開伺帘。包含一個(gè)模版測試類和兩個(gè)測試方法的模版。
運(yùn)行測試忌锯,查看結(jié)果
現(xiàn)在你為你的項(xiàng)目添加了一個(gè)測試伪嫁,然后去開發(fā)測試一些有意義的東西。首先按住鼠標(biāo)指針移動(dòng)到SampleCalcTests在測試導(dǎo)航測試類偶垮,然后點(diǎn)擊運(yùn)行按鈕運(yùn)行該類中的所有測試方法张咳。結(jié)果在方法名稱的右邊,編輯區(qū)方法名的左邊似舵。
因?yàn)槟K測試和性能測試都是空的脚猾,所以測試成功了。并沒有失敗的斷言砚哗。measureBlock:處單擊左側(cè)的“鉆石”會顯示性能測試的結(jié)果龙助。
這個(gè)面板允許設(shè)置性能基線以及編輯基線和最大STDDREV參數(shù)。
編輯測試和重新運(yùn)行
這個(gè)實(shí)例項(xiàng)目是一個(gè)計(jì)算器應(yīng)用程序蛛芥,你需要檢查加提鸟、減、乘仅淑、除算法的正確性称勋,以及測試其他計(jì)算器功能的操作。測試是在項(xiàng)目中添加和編寫的涯竟,你可以測試任何你想要的測試赡鲜。(這就要求你有一個(gè)很好的代碼結(jié)構(gòu)來提供測試)
eg:你可以在SampleCalcTests.m中添加實(shí)例聲明和引入類。
<pre><code>
import <XCTest/XCTest.h>
//
// Import the application specific header files
import "CalcViewController.h"
import "CalcAppDelegate.h"
@interface CalcTests : XCTestCase {
// add instance variables to the CalcTests class
@private
- NSApplication *app;
- CalcAppDelegate *appDelegate;
- CalcViewController *calcViewController;
- NSView *calcView;
}
*@end
</code></pre>
然后給測試方法的起一個(gè)描述性的名稱庐船,如testAddition并添加要實(shí)施的方法银酬。
<pre><code>
*- (void) testAddition
*{
*//obtain the app variables for test access
*App = [NSApplication sharedApplication];
calcViewController = (CalcViewController)[[NSApplicationsharedApplication] delegate];
*calcView = calcViewController.view;
*//perform two addition tests
*[calcViewController press:[calcView viewWithTag: 6]]; // 6
*[calcViewController press:[calcView viewWithTag:13]]; // +
*[calcViewController press:[calcView viewWithTag: 2]]; // 2
*[calcViewController press:[calcView viewWithTag:12]]; // =
*XCTAssertEqualObjects([calcViewController.displayField stringValue],@"8", @"Part 1 failed.");
*[calcViewController press:[calcView viewWithTag:13]]; // +
*[calcViewController press:[calcView viewWithTag: 2]]; // 2
*[calcViewController press:[calcView viewWithTag:12]]; // =
*XCTAssertEqualObjects([calcViewController.displayField stringValue],@"10", @"Part 2 failed.");
}
</code></pre>
如果你改變了測試的方法,測試導(dǎo)航列表也會做相應(yīng)的改變筐钟。
編輯完以后可以使用測試導(dǎo)航(或者gutter)來運(yùn)行testAddition方法揩瞪。
當(dāng)一個(gè)斷言失敗,在測試導(dǎo)航和gutter會突出顯示盗棵。根據(jù)提示信息你可以非常輕易的找到這個(gè)錯(cuò)誤壮韭。進(jìn)行修改之后就能夠運(yùn)行成功北发。
使用setUp()和tearDown()方法
Xcode運(yùn)行一個(gè)測試包的時(shí)候會走這個(gè)測試類中的所有方法。那這個(gè)測試類中如果都需要一個(gè)初始化對象喷屋,你就要在每一個(gè)方法中對這個(gè)對象進(jìn)行初始化琳拨,這樣就會造成很多重復(fù)的代碼。但是XCTest框架提供了兩個(gè)實(shí)例方法用于測試類的初始化和釋放屯曹。你可以用這兩個(gè)實(shí)例方法將這些共同調(diào)用的方法寫進(jìn)去狱庇。
使用setup和teardown方法非常簡單。
<code><pre>
*- (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;
}
</code></pre>
Setup方法會在測試方法之前調(diào)用恶耽,所以測試方法可以直接試用初始化過的屬性密任。
概要
從這個(gè)簡短的快速入門可以看出來,為一個(gè)項(xiàng)目添加測試是很簡單的偷俭。但是還是有一些注意事項(xiàng):
- Xcode中設(shè)置了大部分的基本測試配置浪讳。當(dāng)你添加一個(gè)新的測試的時(shí)候,Xcode會自動(dòng)為你添加這些測試方法涌萤。使用一個(gè)單獨(dú)的方法進(jìn)行測試淹遵,可以在測試導(dǎo)航中找到。
- 測試導(dǎo)航可以讓你輕松的找到編輯測試的方法负溪,你可以運(yùn)行透揣,在導(dǎo)航測試或者gutter。測試失敗的時(shí)候你可以在gutter中看到失敗的標(biāo)志川抡。
- 單個(gè)測試方法可以包括多個(gè)斷言辐真,從而導(dǎo)致單一的合格或者不合格的測試結(jié)果。你可以根據(jù)需求來做簡單或者復(fù)雜的測試崖堤。setup和teardown實(shí)例方法可以讓你將通用的代碼寫在里邊侍咱。
基礎(chǔ)測試
測試是指檢驗(yàn)?zāi)愕膽?yīng)用程序代碼和庫代碼能否成功運(yùn)行的過程,用于衡量預(yù)期結(jié)果倘感。通過執(zhí)行一些操作放坏,測試可在執(zhí)行一些操作后檢查一個(gè)對象的實(shí)例變量的狀態(tài)咙咽,以確定你的代碼在受到邊界條件變化時(shí)是否會拋出一個(gè)特定的異常等老玛。
定義測試范圍
所有的軟件都是通過很多的單元組合起來的,也就是說钧敞,小的組件合在一起形成較大的蜡豹、功能更強(qiáng)的高級組件,直到符合項(xiàng)目的需求溉苛。良好的測試需要涵蓋該組合的所有功能镜廉。其中單元測試通常處理該項(xiàng)目功能級的小組件。而XCTest允許你為任何層次結(jié)構(gòu)的各個(gè)級別的組件編寫相應(yīng)的測試愚战。
測試組件由什么構(gòu)成完全取決于你自己娇唯,可以是一個(gè)類中的一個(gè)方法齐遵,也可以是完成一個(gè)基本目的的一組方法。例如塔插,一個(gè)算術(shù)運(yùn)算梗摇,參見蘋果的官方demo。處理tableView的內(nèi)容間和代碼數(shù)據(jù)結(jié)構(gòu)中持有列表名稱間的交互有不同的方法想许。每個(gè)方法的操作都意味著應(yīng)用程序功能的組成部分對它的測試伶授。一個(gè)測試組件的行為應(yīng)該是完全確定的,無論測試成功或者失敗流纹。
把你的應(yīng)用程序的行為劃分為越多的組件糜烹,就越能有效的測試你的代碼能否滿足參考標(biāo)準(zhǔn)的各種細(xì)節(jié),尤其是當(dāng)項(xiàng)目不斷的迭代更新的時(shí)候漱凝。對于很多組件組成的大型項(xiàng)目來說疮蹦,你需要運(yùn)行很多的測試來徹底檢測整個(gè)項(xiàng)目。如果可能的話茸炒,測試應(yīng)該快速運(yùn)行挚币,擔(dān)憂一些測試確實(shí)很大,所以運(yùn)行可能會慢一點(diǎn)扣典。當(dāng)有一些故障出現(xiàn)的時(shí)候妆毕,可以運(yùn)行一些小的測試快速測試,這樣可以輕松診斷和修復(fù)問題贮尖。
為項(xiàng)目組件設(shè)計(jì)測試是測試驅(qū)動(dòng)開發(fā)(test-driven-development TDD)的基礎(chǔ)笛粘,也是一種編寫代碼測試之前編寫測試邏輯的編碼方式。這種開發(fā)方法可以讓你在實(shí)施之前確定代碼需求和邊界情況湿硝。編寫測試后薪前,開發(fā)旨在通過測試的算法。在代碼通過測試以后关斜,你才有了提高代碼的基礎(chǔ)示括,才有信心在下一次運(yùn)行這些測試時(shí)能鑒定一些預(yù)期行為(導(dǎo)致你的產(chǎn)品產(chǎn)生BUG)的變化。
甚至在你不使用測試驅(qū)動(dòng)開發(fā)時(shí)痢畜,測試還可以降低修改代碼引入的BUG數(shù)量垛膝,從而幫你提高代碼的特性和功能。在一款運(yùn)行的應(yīng)用程序中進(jìn)行測試以確保未來的更改不會改變應(yīng)用的行為丁稀。當(dāng)你修復(fù)這些BUG后吼拥,你需要添加測試以確保該BUG已經(jīng)被修復(fù)。測試還可以檢測你的代碼线衫,所以有成功和失敗兩種預(yù)期凿可,以覆蓋所有邊界條件。
注意:為一個(gè)沒有考慮到測試的項(xiàng)目添加測試可能會要求重構(gòu)部分代碼來使測試變得更加簡單授账】菖埽“Writing Testable Code”包含游泳的編寫可測試代碼的簡單指南惨驶。
組件可以包括你的應(yīng)用程序的各部分之間的交互。由于有些測試可能需要很長時(shí)間敛助,所以你可能希望定期或者只在一臺服務(wù)器上運(yùn)行他們敞咧。(你可以組織自己的測試并以多種方式運(yùn)行它們,以滿足不同的需求)辜腺。
性能測試
測試的組件可以同時(shí)測試功能和記錄性能休建。使用XCTest提供的API你可以測量以時(shí)間為基準(zhǔn)的性能測試,對一個(gè)相似的方法或者功能你可以跟蹤性能的提高或者退化评疗。
為了衡量一個(gè)性能測試的成功或者失敗测砂,測試必須有一個(gè)基準(zhǔn)用來評估“俅遥基線是運(yùn)行10次以后計(jì)算出來的平均時(shí)間的性能測試砌些。如果與基線相差太多的時(shí)候?yàn)槭 ?**注意:當(dāng)你第一次運(yùn)行性能測試的時(shí)候系統(tǒng)會提示失敗,因?yàn)榈谝淮芜\(yùn)行的時(shí)候基線是未知的加匈。一旦你設(shè)定了一個(gè)測量準(zhǔn)線存璃,XCTest會報(bào)告成功或者失敗,并提示相信的結(jié)果信息雕拼。**
用戶界面測試
功能測試和性能測試一般都被稱為單元測試纵东,其中的單元是相對于組件和最小的模塊來確定的(大概意思)。單元測試主要是讓相關(guān)的組件能夠按照預(yù)期的那樣交互啥寇。從設(shè)計(jì)的角度來看偎球,單元測試是在開發(fā)的時(shí)候編寫的滿足你的預(yù)期。
用戶通過源代碼進(jìn)行界面的交互辑甜。界面的交互一般是整合一整個(gè)子系統(tǒng)的操作來實(shí)現(xiàn)預(yù)期的功能衰絮。這些很難使用單元測試來進(jìn)行測試,這種特殊的測試被稱為UI測試磷醋。
UI測試更貼近于用戶的體驗(yàn)猫牡。你可以編寫模擬事件添加到UI測試中,捕捉這些對象的反應(yīng)邓线,然后測試正確性和性能和單元測試十分類似淌友。
應(yīng)用程序測試和庫測試
Xcode測試提供兩種測試:應(yīng)用程序測試和庫測試。
應(yīng)用程序測試褂痰。應(yīng)用程序測試可以檢查App的代碼組件亩进,例如蘋果測試的官方demo。你可以利用應(yīng)用程序來確保你的UI控件保持原有的位置缩歪,并且你的控件和控制器對象能夠和對象模型正確地工作。
庫測試谍憔。庫測試可檢查獨(dú)立代碼(不再應(yīng)用程序中運(yùn)行的代碼)的行為是否正確匪蝙。利用庫測試主籍,你可以將整個(gè)庫的組件放在一起,通常是測試庫的對象和方法逛球。你也可以使用庫測試來執(zhí)行代碼的壓力測試千元,以確保它在極端的情況下也能正確執(zhí)行(不大可能出現(xiàn)在一個(gè)運(yùn)行的app中)。這些測試可以幫助你生成一個(gè)“健壯的”代碼颤绕,即使在沒有預(yù)料的情況下也能運(yùn)行正常幸海。
XCTest-Xcode測試框架
XCTest是一個(gè)Xcode5及以上版本中使用的測試框架。如果你以前使用過Xcode OCUnit測試奥务,你可能會發(fā)現(xiàn)XCTest和OCUnit有些相似物独。XCTest是OCUnit更現(xiàn)代化的替代,可以更好的與Xcode集成氯葬,為將來Xcode測試功能的改進(jìn)奠定了基礎(chǔ)挡篓。Xcode把XCTest.framework并入你的項(xiàng)目,而不是SenTesting.framework帚称。該框架提供可以讓你設(shè)計(jì)測試并在代碼中運(yùn)行的API官研。
**注意:Xcode包括一個(gè)遷移助手,可用來轉(zhuǎn)換包含OCUnit測試的項(xiàng)目闯睹。更多OCUnit想XCTest轉(zhuǎn)換的詳細(xì)信息戏羽,請參閱“Transitioning frome OCUnit to XCTest”**
測試從哪里運(yùn)行
當(dāng)你開始創(chuàng)建測試的時(shí)候,記住下面的方法:
- 專注于測試你的代碼的最基礎(chǔ)的功能楼吃、模型類蛛壳、方法,它們與控制器相交互所刀。
應(yīng)用程序的高級框圖很可能會包含Model衙荐、View和Controller類別,對于每個(gè)使用Cocoa和Cocoa Touch的開發(fā)者來說浮创,這是一個(gè)熟悉設(shè)計(jì)模式忧吟。當(dāng)你編寫要覆蓋所有Model類別的測試時(shí),你必須要知道App的基礎(chǔ)已經(jīng)進(jìn)行了良好的測試斩披,而且要編寫Controller Classes測試之前溜族,它將帶你接觸你的應(yīng)用程序更復(fù)雜的部分。 - 作為一個(gè)可選的起始點(diǎn)垦沉,如果你正在編寫一個(gè)框架或庫煌抒,你可能想從App接口開始。從那里你可以按照你的方式進(jìn)入內(nèi)部類厕倍。
編寫測試類與方法
但你使用測試導(dǎo)航面板往項(xiàng)目中添加測試target的時(shí)候寡壮,Xcode會在測試導(dǎo)航面板里展示除測試類和測試方法。在測試target里是包含測試方法的測試類。
測試target况既、測試包这溅、測試導(dǎo)航
在學(xué)習(xí)創(chuàng)建測試類前,有必要看看測試導(dǎo)航面板棒仍。它對創(chuàng)建和運(yùn)行測試工作極為重要悲靴。
測試導(dǎo)航面板羅列了測試包里的所有組件內(nèi)容,并在一個(gè)層次列表里展示出測試類和測試方法莫其。下邊是一個(gè)工程的測試導(dǎo)航面板視圖癞尚,包含了多個(gè)測試目標(biāo),展示了測試包乱陡、測試類浇揩、以及測試方法的嵌套層級。
測試包里可以包含多個(gè)測試類蛋褥。你可以使用測試類把測試分到相關(guān)的組群里临燃,或者按照功能分,或者按照組織目的分烙心。例如蘋果測試的官方demo膜廊,創(chuàng)建了BasicFunctionsTests、AdvancedFunctionsTests淫茵、DisplayTests classes三個(gè)類爪瓜,但它們都屬于Mac_Calc_Tests測試包。
一些測試類型可能會共享某些類型的setup和teardown匙瘪,把這些測試整合到類里邊會更加合理铆铆,這樣可以最小化每個(gè)測試方法所需的編寫代碼。
創(chuàng)建測試
可以使用加號按鈕在導(dǎo)航測試面板中選中“New Test Class”命令來創(chuàng)建新測試類丹喻。
基于你在配置頁面鍵入的測試類名薄货,你添加的每一個(gè)類都會使得一個(gè)名為TestClassName.m的文件被添加到項(xiàng)目中。
注意:所有的測試類都是XCTest框架XCTestCase類的子類碍论。
盡管Xcode會默認(rèn)的把測試類添加到工程測試項(xiàng)目所創(chuàng)建的組中谅猾,你還是可以在項(xiàng)目中組織自己選擇的文件。當(dāng)你按下Next按鈕鳍悠,標(biāo)準(zhǔn)的Xcode添加文件頁面如下所示:
你可以使用相同的方法在工程導(dǎo)航面板中添加文件税娜。具體使用當(dāng)法詳見“Adding an Existing File or Folder”。
注意:當(dāng)你用Xcode5及以上版本創(chuàng)建工程時(shí)藏研,一個(gè)測試target和相關(guān)的測試包都會被默認(rèn)的創(chuàng)建敬矩,名稱根據(jù)工程名獲得。比如創(chuàng)建名為MyApp的項(xiàng)目蠢挡,則會自動(dòng)生成一個(gè)名為MyAppTests的測試包弧岳,以及一個(gè)名為MyAppTests的測試類凳忙,關(guān)聯(lián)在MyAppTests.m實(shí)例文件中。
測試類的結(jié)構(gòu)
測試類包含以下的基礎(chǔ)結(jié)構(gòu):
<code><pre>
*#import <XCTest/XCTest.h>
*@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
</code></pre>
測試類用Objective-C實(shí)現(xiàn)缩筛。注意實(shí)現(xiàn)里包含了方法消略,比如setup和teardown的基本實(shí)例方法堡称。這些方法是必須的瞎抛。如果類中的所有的測試方法都需要相同的代碼,你可以定制setup和teardown來包含這些代碼却紧。你添加的代碼在每一個(gè)測試方法的之前和之后調(diào)用桐臊。你可以選擇添加定制的設(shè)置(+ (void)setUp)和卸載teardown(+ (void)tearDown)方法,它們在類里所有的測試方法的之前和之后調(diào)用晓殊。Xcode執(zhí)行測試可以明確這些方法的使用断凶。
測試執(zhí)行的流程
在執(zhí)行測試的過程中,XCTest找到所有集成與XCTestCase(它是測試類)的類巫俺,為每一個(gè)類運(yùn)行它們的測試方法认烁。
對于每個(gè)類來說,測試開始于運(yùn)行類的setup方法介汹。對于每個(gè)測試方法來說却嗡,一個(gè)新的類實(shí)例被創(chuàng)建,他的實(shí)例setup方法就會執(zhí)行嘹承。在跑完測試方法之后窗价,實(shí)例teardown方法。類中這樣連續(xù)重復(fù)執(zhí)行所有的測試方法叹卷。在運(yùn)行了teardown最后的測試方法后撼港,Xcode會執(zhí)行類teardown方法,并開始下一個(gè)類骤竹。這種序列已知重復(fù)直到跑完所有測試類的所有測試方法帝牡。
編寫測試方法
你通過編寫測試方法把測試寫到測試類中,一個(gè)測試方法是以test開頭的測試類的實(shí)例方法蒙揣,沒有參數(shù)靶溜,返回void,比如TestColorsRed測試方法調(diào)用工程中的代碼鸣奔,如果代碼沒有產(chǎn)生預(yù)期的效果墨技,那么會用一系列的斷言API報(bào)錯(cuò)。比如挎狸,一個(gè)函數(shù)返回值可能于預(yù)期相比不同扣汪,或者你的測試方法使用了某個(gè)不適當(dāng)?shù)姆椒ǘ紝伋霎惓!锨匆!癤CTest Assertions”描述了這些情況崭别。
為了是測試方法能夠正常訪問被測代碼冬筒,引入正確的頭文件到測試類中很重要。
當(dāng)Xcode運(yùn)行測試時(shí)茅主,它調(diào)用的每個(gè)測試方法都是獨(dú)立的舞痰。因此每個(gè)方法需要準(zhǔn)備和清理輔助變量、結(jié)構(gòu)以及與主題API進(jìn)行交互的對象等诀姚。如果類中所有的測試方法的代碼是相同的响牛,你可以直接把它添加到必走的setup和teardown的實(shí)例方法中,詳見“Test Class Structure”赫段。
下邊是一個(gè)測試方法的模型:
<code><pre>
*- (void)testColorIsRed {
- *// Set up, call test subject API. (Codecould be shared in setUp method.)
- // Test logic and values, assertions reportpass/fail to testing framework.
- // Tear down. (Code could be shared intearDown method.
}
</code></pre>
這里有一個(gè)簡單的測試方法例子呀打,檢查是否成功為SampleCalc創(chuàng)建了CalcView實(shí)例,詳見“快速啟動(dòng)”糯笙。
<code><pre>
*- (void) testCalcView {
- // setup
- app = [NSApplication sharedApplication];
- calcViewController =(CalcViewController*)[NSApplication sharedApplication] delegate];
- calcView = calcViewController.view;
- XCTAssertNotNil(calcView, @"Cannot findCalcView instance");
- // no teardown needed
}
</code></pre>
編寫異步操作測試
測試是同步的贬丛,因?yàn)橹挥挟?dāng)上一次測試結(jié)束以后才進(jìn)行下一個(gè)測試。但是越來越多的代碼使用異步執(zhí)行给涕。為了處理這些異步調(diào)用執(zhí)行的方法和功能組件豺憔,Xcode6增強(qiáng)了包括序列化異步執(zhí)行測試方法的能力,等待異步回調(diào)或者超時(shí)完成够庙。
例如:
<code><pre>
*// 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.
- *XCTestExpectation *documentOpenExpectation = [selfexpectationWithDescription:@"document open"];
- *NSURL *URL =[[NSBundle bundleForClass:[self class]]
URLForResource:@"TestDocument"withExtension:@"mydoc"];
- UIDocumentdoc = [[UIDocument alloc] initWithFileURL:URL];
- *[docopenWithCompletionHandler:^(BOOL success) {
*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:1 handler:^(NSError *error) {
*[doc closeWithCompletionHandler:nil];
- *}];
*}
</code></pre>
有關(guān)更多異步操作的相信信息恭应,請參閱“XCTest.framework”下的XCTestCase+AsynchronousTesting.h文件。
性能測試
性能測試就是在代碼塊中運(yùn)行10次首启,收集平均執(zhí)行時(shí)間和和標(biāo)準(zhǔn)的偏差暮屡。這些值形成一個(gè)平均值,用來評估和基線對比的成功或者失敗。
**注意:基線是您指定要用于檢測合格與否的瓶價(jià)值。該報(bào)告的UI提供了一種機(jī)制來設(shè)置或者更改基準(zhǔn)值辛藻。**
為了實(shí)現(xiàn)性能測試端圈,在Xcode6以后當(dāng)中使用新的XCTest方法的API。
<code><pre>
*- (void)testPerformanceExample{
- *// This is an example of a performance testcase.
- *[self measureBlock:^{
*// Put the code you want to measure thetime of here.
- }];
*}
</code></pre>
下面的例子簡單的演示了一個(gè)用計(jì)算器應(yīng)用程序編寫的性能測試的測試速度。一個(gè)measureBlock隨著時(shí)間的增加XCTest迭代。
<code><pre>
*- (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]]; // =
*}
- *}];
}
</code></pre>
運(yùn)行一次性能測試,在測試導(dǎo)航面板的導(dǎo)航器中提供信息彻秆。點(diǎn)擊該信息會顯示運(yùn)行出來的值。結(jié)果顯示包括控制設(shè)置的結(jié)果作為準(zhǔn)線和未來的測試做對比结闸〈蕉遥基線存儲了每個(gè)設(shè)備的配置,所以你相同的測試在不同的設(shè)備上執(zhí)行桦锄,會有不同的準(zhǔn)線扎附。(取決于配置的處理速度,內(nèi)存等等)
注意:性能測試總是在第一次運(yùn)行结耀,直到準(zhǔn)線被設(shè)置在一個(gè)特定的設(shè)備配置中報(bào)告失敗留夜。
有關(guān)性能測試的更多詳細(xì)的信息匙铡,請參閱XCTest.framework下的XCTestCase.h文件。
編寫UI測試
創(chuàng)建XCTest UI測試是單元測試的一個(gè)擴(kuò)展對于相同的編程模型碍粥。參見“User Interface Testing”鳖眼。
編寫swift測試
swift控制器和模型不能訪問程序內(nèi)部和框架內(nèi)部聲明。在Xcode6訪問swift的內(nèi)部功能嚼摩,你需要進(jìn)入公共的切入點(diǎn)來進(jìn)行測試钦讳,降低了swift的安全特性。
Xcode7提供了這個(gè)問題的解決方案:
- swift內(nèi)部訪問時(shí)低斋,測試通過通知編輯器生成進(jìn)行訪問蜂厅。編譯器通過一個(gè)新的控制-enable進(jìn)行更改匪凡,Xcode在接受到這個(gè)通知的時(shí)候生成膊畴。這種行為是控的,對新的項(xiàng)目的默認(rèn)設(shè)置來進(jìn)行設(shè)置病游。他不需要改變源代碼唇跨。
- 通過修改導(dǎo)入頭文件的聲明,來改變測試入口的可見性衬衬。使用新的@testable屬性導(dǎo)入买猖,改變你的測試代碼,不需要修改應(yīng)用代碼滋尉。
<code><pre>
*import Cocoa
*@NSApplicationMain
*class AppDelegate: NSObject, NSApplicationDelegate {
*@IBOutlet weak var window:NSWindow!
*func foo() {
*println("Hello,World!")
*}
}
</code></pre>
編寫一個(gè)測試類玉控,允許訪問Appdelegate類,修改導(dǎo)入的語句與你的測試代碼使用@testable屬性
<code><pre>
*// Importing XCTestbecause of XCTestCase
*import XCTest
*// Importing AppKitbecause of NSApplication
*import AppKit
*// Importing MySwiftAppbecause of AppDelegate
*@testable importMySwiftApp
*class MySwiftAppTests:XCTestCase {
- *func testExample() {
let appDelegate =NSApplication.sharedApplication().delegate as! AppDelegate
appDelegate.foo()
- }
}
</code></pre>
有了這個(gè)解決方案狮惜,你的swift內(nèi)部代碼能夠完全的被測試方法訪問到高诺。
XCTest斷言
你的測試方法使用XCTest框架提供給的斷言來展示Xcode的測試結(jié)果。所有的斷言都有一個(gè)類似的形式:項(xiàng)目比較或邏輯表達(dá)碾篡,一個(gè)失敗的結(jié)果字符串格式虱而,和插入到字符串格式中的參數(shù)。
**注意:所有的斷言最后一個(gè)參數(shù)是format…开泽,格式字符串和變量參數(shù)列表牡拇。XCTest為所有斷言提供了默認(rèn)的失敗結(jié)果字符串,可以使用參數(shù)傳遞到斷言里穆律。Format字符串提供了可選的額外的失敗自定義描述惠呼,就可以進(jìn)一步選擇提供的描述。這個(gè)參數(shù)是可選的峦耘,也可以完全忽略剔蹋。**
例如:
<code><pre>
XCTAssertEqualObjects([calcViewController.displayField stringValue], @"8", @"Part 1 failed.");
</code></pre>
這段簡單明了的描述是說:“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在測試導(dǎo)航面板發(fā)出失敗信號贡歧,然后Xcode會在issues導(dǎo)航面板滩租、源碼編輯器以及其他地方展示失敗的描述赋秀。下面是源代碼編輯器典型的斷言結(jié)果:
測試方法可以包含多個(gè)斷言,如果任何斷言包含失敗報(bào)告律想,那么Xcode都會發(fā)出測試失敗信號猎莲。
斷言氛圍物種類型:無條件報(bào)錯(cuò)、等價(jià)測試技即、nil測試著洼、布爾測試以及異常測試。
用類別區(qū)分?jǐn)嘌?/h3>
下面的區(qū)域列出了XCTest斷言而叼。你可以XCTestAssertions.h中獲取更多斷言的信息身笤。
- 無條件報(bào)錯(cuò)
XCTFail生成一個(gè)無條件的報(bào)錯(cuò)
<code><pre>
XCTFail(format...)
</code></pre>
- 等價(jià)測試
XCTAssertEqualObjectes,當(dāng)expresson1不等于expresson2時(shí)報(bào)錯(cuò)(或者一個(gè)對象為空葵陵,另一個(gè)對象不為空)
<code><pre>
XCTAssertEqualObjects(expression1, expression2, format...)
</code></pre>
XCTAssertNotEqualObjects. 當(dāng)expression1等于expression2時(shí)報(bào)錯(cuò)液荸。
<code><pre>
XCTAssertNotEqualObjects(expression1, expression2, format...)
</code></pre>
XCTAssertEqual. 當(dāng)expression1不等于expression2時(shí)報(bào)錯(cuò),這個(gè)測試用于C語言的標(biāo)量脱篙。
<code><pre>
XCTAssertEqual(expression1, expression2, format...)
</code></pre>
XCTAssertNotEqual. 當(dāng)expression1等于expression2時(shí)報(bào)錯(cuò)娇钱,這個(gè)測試用于C語言的標(biāo)量。
<code><pre>
XCTAssertNotEqual(expression1, expression2, format...)
</code></pre>
XCTAssertEqualWithAccuracy. 當(dāng)expression1和expression2之間的差別高于accuracy 將報(bào)錯(cuò)绊困。這種測試適用于floats和doubles這些標(biāo)量文搂,兩者之間的細(xì)微差異導(dǎo)致它們不完全相等,但是對所有的標(biāo)量都有效秤朗。
<code><pre>
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)
</code></pre>
XCTAssertNotEqualWithAccuracy. 當(dāng)expression1和expression2之間的差別低于accuracy將產(chǎn)生失敗煤蹭。這種測試適用于floats和doubles這些標(biāo)量,兩者之間的細(xì)微差異導(dǎo)致它們不完全相等取视,但是對所有的標(biāo)量都有效硝皂。
<code><pre>
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)
</code></pre>
- Nil(空)測試
XCTAssertNil. 當(dāng)expression參數(shù)非nil時(shí)報(bào)錯(cuò)。
<code><pre>
XCTAssertNil(expression, format...)
</code></pre>
XCTAssertNotNil. 當(dāng)expression參數(shù)為nil時(shí)報(bào)錯(cuò)贫途。
<code><pre>
XCTAssertNotNil(expression, format...)
</code></pre>
- Boolean測試
XCTAssertTrue. 當(dāng)expression計(jì)算結(jié)果為false時(shí)報(bào)錯(cuò)吧彪。
<code><pre>
XCTAssertTrue(expression, format...)
</code></pre>
XCTAssert. 當(dāng)expression計(jì)算結(jié)果為false時(shí)報(bào)錯(cuò),與XCTAssertTrue同義丢早。
<code><pre>
XCTAssert(expression, format...)
</code></pre>
XCTAssertFalse. 當(dāng)expression計(jì)算結(jié)果為true報(bào)錯(cuò)姨裸。
<code><pre>
XCTAssertFalse(expression, format...)
</code></pre>
- 異常測試
XCTAssertThrows.當(dāng)expression不拋出異常時(shí)報(bào)錯(cuò)。
<code><pre>
XCTAssertThrows(expression, format...)
</code></pre>
XCTAssertThrowsSpecific.當(dāng)expression針對指定類不拋出異常時(shí)報(bào)錯(cuò)怨酝。
<code><pre>
XCTAssertThrowsSpecific(expression, exception_class, format...)
</code></pre>
XCTAssertThrowsSpecificNamed. 當(dāng)expression針對特定類和特定名字不拋出異常時(shí)報(bào)錯(cuò)傀缩。對于AppKit框架或Foundation框架非常有用,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)农猬。
<code><pre>
XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, format...)
</code></pre>
XCTAssertNoThrow. 當(dāng)expression拋出異常時(shí)報(bào)錯(cuò)赡艰。
<code><pre>
XCTAssertNoThrow(expression, format...)
</code></pre>
XCTAssertNoThrowSpecific. 當(dāng)expression針對指定類拋出異常時(shí)報(bào)錯(cuò)。任意其他異常都可以斤葱;也就是說它不會報(bào)錯(cuò)慷垮。
<code><pre>
XCTAssertNoThrowSpecific(expression, exception_class, format...)
</code></pre>
XCTAssertNoThrowSpecificNamed. 當(dāng)expression針對特定類和特定名字拋出異常時(shí)報(bào)錯(cuò)揖闸。對于AppKit框架或Foundation框架非常有用,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)
<code><pre>
XCTAssertNoThrowSpecificNamed(expression, exception_class, exception_name, format...)
</code></pre>
運(yùn)行測試并查看結(jié)果
使用Xcode測試導(dǎo)航面板料身,可以很容易的運(yùn)行測試并查看結(jié)果汤纸。有另外幾種運(yùn)行測試的交互方法。Xcode運(yùn)行測試取決于一個(gè)scheme中開啟了哪些test target芹血。測試導(dǎo)航面板讓你無需使用scheme編輯器就能直接控制那些被包含贮泞、被開啟或關(guān)閉的test target、類以及方法幔烛。
運(yùn)行測試命令
測試導(dǎo)航面板提供了快捷的方法啃擦,以將運(yùn)行測試作為編碼流程的一部分。測試同樣可以直接在源代碼編輯器里運(yùn)行或者使用product菜單運(yùn)行饿悬。
-
使用測試導(dǎo)航面板
在測試導(dǎo)航面板中令蛉,將鼠標(biāo)停在測試包、類或方法名上時(shí)乡恕,會出現(xiàn)一個(gè)“Run”按鈕言询。你可以運(yùn)行某個(gè)特定測試,也可以運(yùn)行一個(gè)類中的測試或運(yùn)行一個(gè)測試包中的所有測試傲宜,這取決于列表中的鼠標(biāo)停留位置。
將鼠標(biāo)懸停在測試包名上夫啊,并點(diǎn)擊右邊出現(xiàn)的運(yùn)行按鈕來測試一個(gè)包中的所有測試函卒。
將鼠標(biāo)懸停在類名上,并點(diǎn)擊右邊出現(xiàn)的運(yùn)行按鈕來測試一個(gè)類中的所有測試撇眯。
將鼠標(biāo)巡艇在測試方法名上报嵌,并點(diǎn)擊右側(cè)出現(xiàn)的運(yùn)行按鈕來測試一個(gè)單獨(dú)的測試。
- 使用源代碼編輯器
當(dāng)在源代碼編輯器中打開一個(gè)測試類熊榛,每個(gè)測試方法名字旁的邊欄會明顯的指示器锚国。在指示器上懸停鼠標(biāo),出現(xiàn)一個(gè)運(yùn)行按鈕玄坦。點(diǎn)擊按鈕運(yùn)行該測試方法血筑,指示器隨后顯示該測試成功或失敗的狀態(tài)。再次將鼠標(biāo)懸停到指示器上可以再次顯示運(yùn)行按鈕來重復(fù)測試煎楣。這種機(jī)制一次只運(yùn)行一個(gè)測試豺总。
注意:出現(xiàn)在@implementation旁邊的指示器同樣也適用于類,允許你運(yùn)行類中所有的測試择懂。
- 使用Product菜單
- Product菜單包括了從鍵盤直接運(yùn)行測試的快捷命令喻喳。
- Product>Test運(yùn)行當(dāng)前激活的方案(scheme)。鍵盤快捷鍵是Conmmand-U困曙。
- Product>Build for>Testing和Product>Perform Action>Test without Building表伦。這兩個(gè)命令可以用來構(gòu)建測試并運(yùn)行獨(dú)立于其他的測試谦去。這是簡化構(gòu)建和測試進(jìn)程的快捷命令。對于修改了代碼并在構(gòu)建過程中檢查警告或錯(cuò)誤時(shí)蹦哼,這是特別游泳的哪轿,或者如果你知道當(dāng)前的構(gòu)建是最新的,他也可以加速測試過程翔怎。鍵盤快捷方式分別是Shift-Command-U和Control-Command-U窃诉。
- Product>Perform Action>Test。當(dāng)你編輯一個(gè)測試方法時(shí)赤套,這個(gè)動(dòng)態(tài)菜單選項(xiàng)展示當(dāng)前光標(biāo)所處的測試方法飘痛,并允許你使用鍵盤快捷鍵方式來運(yùn)行測試。命令的名稱取決于將要運(yùn)行的測試容握,比如Product>Perform Action>Test testAddition宣脉。快捷鍵Control-Opention-Command-U剔氏。
注意:除了源代碼編輯器塑猖,該命令還基于工程導(dǎo)航面板中的選擇情況運(yùn)行。當(dāng)人和一個(gè)導(dǎo)航面板處于激活狀態(tài)谈跛,源代碼編輯器就是去了焦點(diǎn)羊苟,并且該命令將使用任何一個(gè)導(dǎo)航面板中的當(dāng)前選擇作為輸入。在測試導(dǎo)航面板中感憾,可以選擇測試包蜡励、類、或方法阻桅。在工程導(dǎo)航面板中凉倚,可以選擇測試類實(shí)現(xiàn)文件,例如CalcTests.m嫂沉。
- Product>Perform Action>Test Again稽寒。當(dāng)測試方法在調(diào)試/編輯代碼中暴露出問題時(shí),返回最后一個(gè)被執(zhí)行的測試方法非常有用趟章。像Product>Perform Action>Test命令杏糙,運(yùn)行的測試名稱在命令中出現(xiàn),例如Product>Perform Action>Test Again testAddition尤揣。鍵盤的快捷方式Control-Option-Command-G搔啊。
顯示測試結(jié)果
XCTest框架有幾種不同的方式在Xcode中展示測試結(jié)果。下面的屏幕截圖展示了在哪里查看這些測試結(jié)果.
-
在一個(gè)或一組測試運(yùn)行后北戏,你可以在測試導(dǎo)航面板中瀏覽測試通過或者失敗.
如果測試方法被疊加到各自的類中负芋,或測試方法被折疊到測試包中,該標(biāo)識則反映了封閉測試的集合狀態(tài),表明在這個(gè)類或者包中至少有一個(gè)測試方法不通過旧蛾。
-
在源代碼編輯器中莽龟,你可以瀏覽測試通過或者失敗的標(biāo)識和調(diào)試信息
- 在報(bào)告導(dǎo)航面板中,可以通過測試運(yùn)行結(jié)果查看锨天。
對于一個(gè)性能測試毯盈,單擊時(shí)間列中的值,獲得性能測試的詳細(xì)報(bào)告病袄。你可以通過單擊各個(gè)測試運(yùn)行按鈕搂赋,查看10次運(yùn)行的詳細(xì)信息。編輯按鈕可以修改基線和允許通過或者失敗的最大標(biāo)準(zhǔn)偏差益缠。
日志導(dǎo)航面板中脑奠,你可以瀏覽相關(guān)的錯(cuò)誤描述和其他一些輸出摘要。點(diǎn)擊走遍的提示箭頭標(biāo)識幅慌,可以展開所有的測試運(yùn)行細(xì)節(jié)宋欺。
注意:出了左邊展開的三角圖標(biāo),測試失敗項(xiàng)右邊的小圖標(biāo)可以展開顯示更多信息胰伍。
-
調(diào)試控制臺以文本形式展示了測試運(yùn)行的綜合信息齿诞。這些信息和日志導(dǎo)航面板中顯示的信息一樣。但如果你已經(jīng)處于debug狀態(tài)骂租,那么debug的輸出也會出現(xiàn)在這里祷杈。
使用Schemes(方案)和Test Target(測試目標(biāo))
Xcode Scheme控制著構(gòu)建、運(yùn)行菩咨、測試和調(diào)試這些菜單命令的行為吠式。當(dāng)創(chuàng)建Test Target并使用測試導(dǎo)航面板執(zhí)行其他測試系統(tǒng)操作時(shí),Xcode5為我們管理Scheme配置——例如抽米,當(dāng)你開啟或者關(guān)閉一個(gè)測試方法、測試類或測試包時(shí)糙置。使用Xcode Server和持續(xù)集成需要通過設(shè)置Manager Schemes頁面中的復(fù)選框來將一個(gè)Scheme設(shè)置稱共享云茸,并將其連同你的工程和源代碼導(dǎo)出到一個(gè)源文件倉庫。
下面的區(qū)域列出了XCTest斷言而叼。你可以XCTestAssertions.h中獲取更多斷言的信息身笤。
XCTFail生成一個(gè)無條件的報(bào)錯(cuò)
<code><pre>
XCTFail(format...)
</code></pre>
XCTAssertEqualObjectes,當(dāng)expresson1不等于expresson2時(shí)報(bào)錯(cuò)(或者一個(gè)對象為空葵陵,另一個(gè)對象不為空)
<code><pre>
XCTAssertEqualObjects(expression1, expression2, format...)
</code></pre>
XCTAssertNotEqualObjects. 當(dāng)expression1等于expression2時(shí)報(bào)錯(cuò)液荸。
<code><pre>
XCTAssertNotEqualObjects(expression1, expression2, format...)
</code></pre>
XCTAssertEqual. 當(dāng)expression1不等于expression2時(shí)報(bào)錯(cuò),這個(gè)測試用于C語言的標(biāo)量脱篙。
<code><pre>
XCTAssertEqual(expression1, expression2, format...)
</code></pre>
XCTAssertNotEqual. 當(dāng)expression1等于expression2時(shí)報(bào)錯(cuò)娇钱,這個(gè)測試用于C語言的標(biāo)量。
<code><pre>
XCTAssertNotEqual(expression1, expression2, format...)
</code></pre>
XCTAssertEqualWithAccuracy. 當(dāng)expression1和expression2之間的差別高于accuracy 將報(bào)錯(cuò)绊困。這種測試適用于floats和doubles這些標(biāo)量文搂,兩者之間的細(xì)微差異導(dǎo)致它們不完全相等,但是對所有的標(biāo)量都有效秤朗。
<code><pre>
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)
</code></pre>
XCTAssertNotEqualWithAccuracy. 當(dāng)expression1和expression2之間的差別低于accuracy將產(chǎn)生失敗煤蹭。這種測試適用于floats和doubles這些標(biāo)量,兩者之間的細(xì)微差異導(dǎo)致它們不完全相等取视,但是對所有的標(biāo)量都有效硝皂。
<code><pre>
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)
</code></pre>
XCTAssertNil. 當(dāng)expression參數(shù)非nil時(shí)報(bào)錯(cuò)。
<code><pre>
XCTAssertNil(expression, format...)
</code></pre>
XCTAssertNotNil. 當(dāng)expression參數(shù)為nil時(shí)報(bào)錯(cuò)贫途。
<code><pre>
XCTAssertNotNil(expression, format...)
</code></pre>
XCTAssertTrue. 當(dāng)expression計(jì)算結(jié)果為false時(shí)報(bào)錯(cuò)吧彪。
<code><pre>
XCTAssertTrue(expression, format...)
</code></pre>
XCTAssert. 當(dāng)expression計(jì)算結(jié)果為false時(shí)報(bào)錯(cuò),與XCTAssertTrue同義丢早。
<code><pre>
XCTAssert(expression, format...)
</code></pre>
XCTAssertFalse. 當(dāng)expression計(jì)算結(jié)果為true報(bào)錯(cuò)姨裸。
<code><pre>
XCTAssertFalse(expression, format...)
</code></pre>
XCTAssertThrows.當(dāng)expression不拋出異常時(shí)報(bào)錯(cuò)。
<code><pre>
XCTAssertThrows(expression, format...)
</code></pre>
XCTAssertThrowsSpecific.當(dāng)expression針對指定類不拋出異常時(shí)報(bào)錯(cuò)怨酝。
<code><pre>
XCTAssertThrowsSpecific(expression, exception_class, format...)
</code></pre>
XCTAssertThrowsSpecificNamed. 當(dāng)expression針對特定類和特定名字不拋出異常時(shí)報(bào)錯(cuò)傀缩。對于AppKit框架或Foundation框架非常有用,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)农猬。
<code><pre>
XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, format...)
</code></pre>
XCTAssertNoThrow. 當(dāng)expression拋出異常時(shí)報(bào)錯(cuò)赡艰。
<code><pre>
XCTAssertNoThrow(expression, format...)
</code></pre>
XCTAssertNoThrowSpecific. 當(dāng)expression針對指定類拋出異常時(shí)報(bào)錯(cuò)。任意其他異常都可以斤葱;也就是說它不會報(bào)錯(cuò)慷垮。
<code><pre>
XCTAssertNoThrowSpecific(expression, exception_class, format...)
</code></pre>
XCTAssertNoThrowSpecificNamed. 當(dāng)expression針對特定類和特定名字拋出異常時(shí)報(bào)錯(cuò)揖闸。對于AppKit框架或Foundation框架非常有用,拋出帶有特定名字的NSException(NSInvalidArgumentException等等)
<code><pre>
XCTAssertNoThrowSpecificNamed(expression, exception_class, exception_name, format...)
</code></pre>
使用Xcode測試導(dǎo)航面板料身,可以很容易的運(yùn)行測試并查看結(jié)果汤纸。有另外幾種運(yùn)行測試的交互方法。Xcode運(yùn)行測試取決于一個(gè)scheme中開啟了哪些test target芹血。測試導(dǎo)航面板讓你無需使用scheme編輯器就能直接控制那些被包含贮泞、被開啟或關(guān)閉的test target、類以及方法幔烛。
測試導(dǎo)航面板提供了快捷的方法啃擦,以將運(yùn)行測試作為編碼流程的一部分。測試同樣可以直接在源代碼編輯器里運(yùn)行或者使用product菜單運(yùn)行饿悬。
使用測試導(dǎo)航面板
在測試導(dǎo)航面板中令蛉,將鼠標(biāo)停在測試包、類或方法名上時(shí)乡恕,會出現(xiàn)一個(gè)“Run”按鈕言询。你可以運(yùn)行某個(gè)特定測試,也可以運(yùn)行一個(gè)類中的測試或運(yùn)行一個(gè)測試包中的所有測試傲宜,這取決于列表中的鼠標(biāo)停留位置。
將鼠標(biāo)懸停在測試包名上夫啊,并點(diǎn)擊右邊出現(xiàn)的運(yùn)行按鈕來測試一個(gè)包中的所有測試函卒。
將鼠標(biāo)懸停在類名上,并點(diǎn)擊右邊出現(xiàn)的運(yùn)行按鈕來測試一個(gè)類中的所有測試撇眯。
將鼠標(biāo)巡艇在測試方法名上报嵌,并點(diǎn)擊右側(cè)出現(xiàn)的運(yùn)行按鈕來測試一個(gè)單獨(dú)的測試。
當(dāng)在源代碼編輯器中打開一個(gè)測試類熊榛,每個(gè)測試方法名字旁的邊欄會明顯的指示器锚国。在指示器上懸停鼠標(biāo),出現(xiàn)一個(gè)運(yùn)行按鈕玄坦。點(diǎn)擊按鈕運(yùn)行該測試方法血筑,指示器隨后顯示該測試成功或失敗的狀態(tài)。再次將鼠標(biāo)懸停到指示器上可以再次顯示運(yùn)行按鈕來重復(fù)測試煎楣。這種機(jī)制一次只運(yùn)行一個(gè)測試豺总。
注意:出現(xiàn)在@implementation旁邊的指示器同樣也適用于類,允許你運(yùn)行類中所有的測試择懂。
注意:除了源代碼編輯器塑猖,該命令還基于工程導(dǎo)航面板中的選擇情況運(yùn)行。當(dāng)人和一個(gè)導(dǎo)航面板處于激活狀態(tài)谈跛,源代碼編輯器就是去了焦點(diǎn)羊苟,并且該命令將使用任何一個(gè)導(dǎo)航面板中的當(dāng)前選擇作為輸入。在測試導(dǎo)航面板中感憾,可以選擇測試包蜡励、類、或方法阻桅。在工程導(dǎo)航面板中凉倚,可以選擇測試類實(shí)現(xiàn)文件,例如CalcTests.m嫂沉。
XCTest框架有幾種不同的方式在Xcode中展示測試結(jié)果。下面的屏幕截圖展示了在哪里查看這些測試結(jié)果.
在一個(gè)或一組測試運(yùn)行后北戏,你可以在測試導(dǎo)航面板中瀏覽測試通過或者失敗.
如果測試方法被疊加到各自的類中负芋,或測試方法被折疊到測試包中,該標(biāo)識則反映了封閉測試的集合狀態(tài),表明在這個(gè)類或者包中至少有一個(gè)測試方法不通過旧蛾。
在源代碼編輯器中莽龟,你可以瀏覽測試通過或者失敗的標(biāo)識和調(diào)試信息
對于一個(gè)性能測試毯盈,單擊時(shí)間列中的值,獲得性能測試的詳細(xì)報(bào)告病袄。你可以通過單擊各個(gè)測試運(yùn)行按鈕搂赋,查看10次運(yùn)行的詳細(xì)信息。編輯按鈕可以修改基線和允許通過或者失敗的最大標(biāo)準(zhǔn)偏差益缠。
日志導(dǎo)航面板中脑奠,你可以瀏覽相關(guān)的錯(cuò)誤描述和其他一些輸出摘要。點(diǎn)擊走遍的提示箭頭標(biāo)識幅慌,可以展開所有的測試運(yùn)行細(xì)節(jié)宋欺。
注意:出了左邊展開的三角圖標(biāo),測試失敗項(xiàng)右邊的小圖標(biāo)可以展開顯示更多信息胰伍。
調(diào)試控制臺以文本形式展示了測試運(yùn)行的綜合信息齿诞。這些信息和日志導(dǎo)航面板中顯示的信息一樣。但如果你已經(jīng)處于debug狀態(tài)骂租,那么debug的輸出也會出現(xiàn)在這里祷杈。
Xcode Scheme控制著構(gòu)建、運(yùn)行菩咨、測試和調(diào)試這些菜單命令的行為吠式。當(dāng)創(chuàng)建Test Target并使用測試導(dǎo)航面板執(zhí)行其他測試系統(tǒng)操作時(shí),Xcode5為我們管理Scheme配置——例如抽米,當(dāng)你開啟或者關(guān)閉一個(gè)測試方法、測試類或測試包時(shí)糙置。使用Xcode Server和持續(xù)集成需要通過設(shè)置Manager Schemes頁面中的復(fù)選框來將一個(gè)Scheme設(shè)置稱共享云茸,并將其連同你的工程和源代碼導(dǎo)出到一個(gè)源文件倉庫。
Scheme配置方法如下:
-
選擇Scheme menu >Manage Scheme谤饭,彈出管理頁标捺。
這個(gè)工程中有兩個(gè)Scheme,一個(gè)用來構(gòu)建應(yīng)用揉抵,一個(gè)用來構(gòu)建框架/庫亡容。右側(cè)的Share復(fù)選框用來將Scheme配置為共享,并允許Xcode Server bots使用冤今。
- 在管理頁中闺兢,雙擊一個(gè)Scheme,顯示Scheme Editor戏罢。一個(gè)Scheme的測試行為標(biāo)識了你執(zhí)行測試命令時(shí)Xcode執(zhí)行的測試屋谭。
注意:測試目標(biāo)脚囊、測試類和測試方法所關(guān)聯(lián)的測試導(dǎo)航面板和配置/設(shè)置助手通常維護(hù)所有關(guān)于測試操作的Scheme設(shè)置。
關(guān)于使用桐磁、配置和編輯Scheme的更多信息可以查看Scheme Configuration Help悔耘,或者視頻WWDC 2012:Working with Scheme and Projects in Xcode。
構(gòu)建測試-測試應(yīng)用我擂、測試庫
應(yīng)用程序在你的應(yīng)用的上下文中運(yùn)行衬以,允許你創(chuàng)建測試,這些測試結(jié)合了不同的類校摩、庫/框架和應(yīng)用功能的角度的行為看峻。庫測試獨(dú)立于你的應(yīng)用,在一個(gè)庫或框架中采用實(shí)驗(yàn)類和方法秧耗,來驗(yàn)證它們的行為符合庫的明確要求备籽。
兩種類型的測試包需要不同的構(gòu)建設(shè)置。在新的target助手中通過選擇目標(biāo)參數(shù)來創(chuàng)建test target時(shí)分井,會執(zhí)行構(gòu)建設(shè)置配置车猬。目標(biāo)助手隨著目標(biāo)下拉菜單顯示。名為SampleCalc的應(yīng)用和名為CalcLibrary的庫可供選擇尺锚。
選擇SampleCalc作為該測試目標(biāo)所關(guān)聯(lián)的構(gòu)建產(chǎn)品配置構(gòu)建設(shè)置來測試一個(gè)應(yīng)用珠闰。測試的執(zhí)行基于應(yīng)用進(jìn)程,測試在得到SampleCalc你可以根據(jù)自己的偏好改變它瘫辩。
如果你選擇CalcLibrary作為關(guān)聯(lián)的構(gòu)建產(chǎn)品伏嗜,目標(biāo)助手將會在配置構(gòu)建設(shè)置來測試庫。Xcode引導(dǎo)測試運(yùn)行時(shí)上下文和框架/庫伐厌,以及你的測試代碼-基于一個(gè)Xcode管理的進(jìn)程承绸。這種情況下默認(rèn)的產(chǎn)品名字來自于庫目標(biāo)(“CalcLibrary Tests”)。同樣你可以基于自己的喜好更改挣轨。
默認(rèn)構(gòu)建設(shè)置
大多數(shù)情況下军熏,配置構(gòu)建設(shè)置來測試應(yīng)用或庫所要做的唯一一件事就是選擇正確的測試目標(biāo)。Xcode則自動(dòng)關(guān)注構(gòu)建設(shè)置管理卷扮。因?yàn)槟憧赡苡幸粋€(gè)需要復(fù)雜構(gòu)建設(shè)置的功能荡澎,所以了解Xcode為應(yīng)用測試和庫測試所建立的標(biāo)準(zhǔn)是非常有用的。
在這里使用官方的測試demo來演示:
-
在工程導(dǎo)航面板中單擊SampleCalc進(jìn)入工程編輯器晤锹,然后選擇SampleCalc Tests應(yīng)用測試目標(biāo)摩幔。在編輯器的General面板中,有一個(gè)目標(biāo)快捷菜單鞭铆。該下拉菜單應(yīng)當(dāng)展示SampleCalc為目標(biāo)或衡。
你可以檢查該構(gòu)建設(shè)置是否正確。
-
點(diǎn)擊構(gòu)建設(shè)置,在搜索框中輸入Bundle Loader薇宠。針對SampleCalc的應(yīng)用測試被SampleCalc App加載偷办。你可以看到針對Debug和Release的作為自定義參數(shù)的可執(zhí)行文件路徑。搜索Test Host也可以看到相同的路徑澄港。
該工程的庫目標(biāo)名為CalcLibrary椒涯,并且已經(jīng)與名為CalcLibraryTests的測試目標(biāo)關(guān)聯(lián)。
-
選擇CalcLibraryTests目標(biāo)并查看General面板回梧。CalcLibrary被作為目標(biāo)废岂。
-
像應(yīng)用測試目標(biāo)一樣,你可以使用build Settings面板查看Bundle Loader和Test Host構(gòu)建設(shè)置狱意,下圖展示Bundle Loader搜索設(shè)置湖苞。
在庫測試目標(biāo)的案例中,Bundle Loader和Test Host項(xiàng)目都沒有關(guān)聯(lián)的參數(shù)详囤。這表明Xcode已經(jīng)默認(rèn)正確配置了它們财骨。
測試的目的
應(yīng)用測試在OS X,iOS(真機(jī))和iOS模擬器上運(yùn)行藏姐。庫測試運(yùn)行在OS X和iOS模擬器上隆箩。Xcode Server可以通過是黨的配置源代碼倉庫,共享Scheme和bot在運(yùn)行OS X Server的Mac上運(yùn)行羔杨。更多關(guān)于Xcode Server運(yùn)行目標(biāo)的信息捌臊,請查看“Automating the Test Process with Continuous Integration”。
調(diào)試測試
所有標(biāo)準(zhǔn)的Xcode調(diào)試工具在執(zhí)行測試的時(shí)候都可以使用兜材。
測試調(diào)試工作流
要確定的第一件事情就是:造成測試失敗的原因是測試中的代碼有BUG還是執(zhí)行的測試方法存在BUG理澎。測試失敗可以指出一些不同類型的問題,即有你的假設(shè)曙寡,在測試中的代碼需求糠爬,也有測試代碼本身,所以調(diào)試測試可以橫跨幾個(gè)不同的工作流举庶。然而通常你的測試方法是相對較小和直接的秩铆,所以最好首先檢查測試的目的是什么,以及它是如何實(shí)現(xiàn)的灯变。
值得注意的一些常見的問題:
測試邏輯是否正確?實(shí)現(xiàn)是否正確捅膘?測試方法用作比較基礎(chǔ)使用的字面值添祸,檢查它們的筆誤和粗舞始終是個(gè)好主意。
假設(shè)是什么寻仗?例如刃泌,你可能在測試方法里使用了錯(cuò)誤的數(shù)據(jù)類型,創(chuàng)建了一個(gè)你所測試的代碼的范圍錯(cuò)誤。
-
是否使用了正確的斷言來報(bào)告耙替,“通過/失敗”狀態(tài)亚侠?例如,可能測試的狀態(tài)需要XCTAssertTure而不是XCTAsserFalse俗扇。有時(shí)候很容易造成這些錯(cuò)誤硝烂。
假設(shè)你的測試假設(shè)是正確的,并且測試方法也正確铜幽,那么錯(cuò)誤一定在要測試的代碼中≈托唬現(xiàn)在定位并修復(fù)它。
具體的測試調(diào)試工具
Xcode有幾個(gè)工具專門用來在你測試時(shí)定位和調(diào)試代碼除抛。
-
測試失敗斷點(diǎn)
在斷電導(dǎo)航面板中(BreakPoint Navigator)狮杨,點(diǎn)擊Add(加號)按鈕,選擇Add Test Failure breakpoint設(shè)置一個(gè)特殊的斷點(diǎn)到忽。
當(dāng)測試方法觸發(fā)了失敗斷言橄教,這個(gè)斷點(diǎn)會終止測試的運(yùn)行。在測試代碼發(fā)生錯(cuò)誤點(diǎn)擊后立馬停止運(yùn)行喘漏,可以讓你快速的找到問題發(fā)生的位置护蝶。你可以看看testAddition測試方法,通過為錯(cuò)誤字符串設(shè)置用來比較的參考標(biāo)準(zhǔn)陷遮,比較字符串被強(qiáng)行斷言為失敗滓走。測試失敗斷點(diǎn)檢測該失敗斷言并停止了該點(diǎn)測試的執(zhí)行。
當(dāng)測試終端帽馋,你也就停止了測試的執(zhí)行搅方。然后在斷言前設(shè)置一個(gè)常規(guī)的斷點(diǎn),再次運(yùn)行測試(為了簡單期間绽族,你可以在源代碼編輯器側(cè)欄中點(diǎn)擊“Run”按鈕來運(yùn)行該測試)姨涡,并繼續(xù)調(diào)試操作來修復(fù)問題。 - 使用工程菜單命令運(yùn)行測試
調(diào)試測試方法時(shí)吧慢,最好記住菜單命令Project>Perform Action>Test Again和Project>Perform Action>Test涛漂。如果你正在測試失敗發(fā)生后編輯修復(fù)代碼,或運(yùn)行你正在編寫的測試方法检诗,它們提供了一個(gè)便捷的方式來測試最后一個(gè)方法匈仗。更多信息請查看“Using the Product menu”。
當(dāng)然你也可以始終使用測試導(dǎo)航面板或源代碼編輯器側(cè)邊欄中的“Run”按鈕來運(yùn)行測試逢慌,都很方便悠轩。 -
輔助編輯器類別
輔助編輯器分類中增加了兩個(gè)專門的分類來運(yùn)行特殊的測試。
- Test Callers category攻泼。如果你修復(fù)了一個(gè)飲用測試失敗的方法火架,你可能會想要檢查該方法在其他測試中是否被調(diào)用并運(yùn)行成功鉴象。帶著這個(gè)問題,在源代碼編輯器中打開輔助編輯器何鸡,并從菜單中選擇Test Classes分類纺弊。你可以從下拉菜單定位到任何調(diào)用它的測試方法的位置,這樣你就可以運(yùn)行它們骡男,以確保你的修復(fù)沒有造成其他的問題淆游。
- Test Classes Category。該分類和Test Callers類似洞翩,不過顯示的是包含測試方法的類列表稽犁,這些方法與主源碼編輯器中編輯類的相關(guān)。對于增加測試來說骚亿,是一個(gè)非常好的機(jī)會已亥,例如給還沒有被并入測試方法中的新方法增加測試。
- 測試時(shí)的異常斷點(diǎn)
通常當(dāng)異常被異常斷點(diǎn)捕獲時(shí)就會終止測試執(zhí)行来屠,所以測試運(yùn)行時(shí)通常都會關(guān)閉異常斷點(diǎn)以避免不適當(dāng)?shù)亩ㄎ粧伋龅臄帱c(diǎn)虑椎。當(dāng)你尋找一個(gè)特定的問題并想終止測試來修復(fù)它時(shí)可以打開異常斷點(diǎn)。