[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.


完成後, 在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