而哪些程式碼是需要被測試的呢?
理想上,只要是自己寫的就需要測試
像是 System function、3rd party library 應該就不需要為他們寫測試碼。
也就是說,我們會寫了一堆程式碼,來整合 System function、3rd party library 來實踐服務
所以我們會需要驗證服務的邏輯是否正確,而使用到的「工具」的反應是否正確,就不是我們要關心的。
因此,功能描述就顯得相對重要,他會決定了服務的面相和測試的範圍。
例如:
- 我使用了系統提供的內建購買功能,來實踐使用者訂閱離線資料庫、自動更新等等功能
這樣的描述,很明確的綁定了一個系統服務,在實作上,可以很單一的考慮這項系統服務的特性來寫作商業邏輯,閱讀上也會很直覺,但是也很容易造成綁定太深,而無法測試。
1 | class MyManager: SystemBuyDelegate { |
iOS 很多系統服務的實踐大概會向上面那樣,使用上很直覺,但是當我們要測試 buy()
時,就會發現一些問題
情境一: SystemBuy.default 只有在實機上有功能,模擬器不提供
當在這樣的狀況時,在模擬器上面跑的 Unit Test 就可能會 Failed
情境二: SystemBuy.default 執行過一次後,就會設定成特定狀態,要 reset 才會回來
跑 Unit Test 不可能隨時隨地 reset 模擬器,當測試跑 N 次, N 次結果都不一樣,會讓這樣的測試無法被信任
總歸一句話,當模組間相互依賴太深,就會難以測試;buy()
這項功能綁訂SystemBuy.default
太深,所以很難測試。
而上面的例子,我們究竟要測試什麼呢?我們要測試的範圍是我們寫過的流程,我們寫過的 code!
觀察一下上面這個模組可能會被如何應用,例如:
1 | class BuyViewController: UIViewController { |
實作一個買東西的功能,介面通常會有一個買東西的按鈕,如果我們要說這個功能正常,也是說
當按下 BuyButton,進行了系統購買的動作,完成後會在 UI 上顯示相對應的動作
在上面的描述中,哪些事我們要測試的呢?
- 按下 BuyButton
- 進行系統購買動作
- 完成後會顯示對應動作
在這裡我們並不會考慮 系統購買是否真的成功
,因為系統購買根本不是我們寫的,我們只會在意成功時要做什麼動作,失敗時要做什麼動作。
以 MyManager
而言,他要對 BuyViewController
保證,當呼叫 buy()
之後,一定會有一個 completionHandler 被呼叫
只要 MyManager
能保證這件事情,也就能說 buy
的「UI 流程」是完整的。
所以當在設計 MyManager
時,要考慮到的就是,如何能疑除掉 SystemBuy.default
,來測試所有我們自行設計的程式碼!
Finish Date: 2017-04-28