[iOS] UnitTest With XCode

此篇, 將利用1個簡單的project來介紹Xcode內建的Unit Test, 該project只會做簡單的幾件事情:

(1.) 當user按下Calculate Button時計算2個輸入數字X與Y的總和, 並將結果顯示在resultLabel上.

(2.) 當user按下Request Button時發送get request, 並將response data顯示在responseTextView上.

(3.) 在viewWillAppear生命週期時清空resultLabel與responseTextView的文字

你可以在這裡下載完整的project.

此Project裡有3個主要的classes,

(1.) ViewController

(在viewWillAppear時呼叫clearData function將label與textView清空)

(2.) Math

add: 將2個數字相加並回傳

stringToInt: string轉int並回傳結果, 若失敗回傳nil

(3.) Network dataTask:

發送一個request並回傳response

建置Unit Test

首先, 如果您的project尚未加入Unit Test, 可以從File -> New -> Target 新建一個Unit Test Bundle.

File -> New -> Target
選擇iOS Unit Testing Bundle

完成後, 在XCode左側目錄欄會發現多了一個Tests的目錄, 且裡面已經幫你建立好了1個default的測試class.

該class的預設內容為:

我們可以注意到, Unit Test用的class必須import XCTest並extend XCTestCase,

這邊有4個function,

setUp: 測試class生命週期, 在測試開始之前被呼叫

tearDown: 測試class生命週期, 在測試完成之後被呼叫

testExample: 預設的test function, 注意到所有的test function命名都必須以test開頭

testPerformanceExample: 預設的test function, 在meaure block裡面的動作皆會執行10次, 用以測試performance

接著, 我們也可以新增新的Test Class分別去測試我們的不同class

MathTest: 用來測試Math class的functions

TestNetwork: 用來測試Network class的dataTask function, 關於網路測試是否成功有2個重點

(1.) request要有發送出去

(2.) 發送出去的url, parameters, headers是否正確

在這個例子裡面我們在response的時候檢查 response?.url?.absoluteString是否跟原本的相同.

然而, 更嚴謹的網路測試通常不會真的發送request出去, 因為這樣會影響測試時間並可能污染server端的資料, 此時就可以用Dependency Injection(DI)等方法來達到測試目的, 詳情可以參考以下連結:

The complete guide to Network Unit Testing in Swift

TestViewController: 用來測試Viewcontroller class, 因Viewcontroller在viewWillAppear裡面呼叫了clearData function, 所以我們在testClearData() 裡面測試相關元件的text是否為空.

這邊需注意:

(1.) test class的Viewcontroller需要用storyboard.instantiateViewController的方式去宣告, 否則IBOutlet元件會為nil

(2. ) 必須呼叫 vc.loadView() 才能啟動Viewcontroller的生命週期

進行測試

點擊Xcode的測試按鈕就能開始測試, 結束後可以在這個頁面看到完整的測試結果, 點擊每個function的綠色勾勾也可以個別測試單個function

測試覆蓋率

(1.) 進入Edit Scheme -> Test -> Options頁面將Gather coverage for all targets選項打勾

(2.) 完成測試後就可以在這裡看到目前測試的coverage rate

Last updated