Android中的互動測試(Interaction Testing in Android)第三部曲:MVVM架構下的互動測試
前情提要
這是Android互動測試系列的最後一篇文章,還沒看過前面幾篇文章的同學,可以參閱:
簡單來說,現在我們要來開發一個可以顯示溫度資訊的App,每次使用者打開APP時,都可以在螢幕上看見當前的氣溫:
以MVVM架構實作
從UML圖中可以很明顯地看出MVVM模式與MVP模式兩者在架構上的差異。
在MVP模式中,View與Presenter彼此是互相依賴的(也可以說它們互相知道彼此的存在),當UI需要刷新時,Presenter會通知View進行刷新。
但是在MVVM的架構之下,View知道ViewModel的存在,但ViewModel卻不需要知道View了,那怎麼知道何時會需要刷新UI呢?其實這邊為了將像是MVP模式中的View與Presenter的耦合解除,引進了觀察者模式(observer pattern),View會持續觀察ViewModel狀態是否有變化,當狀態有異動的時候,UI就會跟著更新了。
實作程式碼
那因為我們要實作的功能實在太簡單了,在這種情境下硬是分太多層會變成over-design(過度設計),所以這邊並不會像Google I/O 2018的App那樣使用use case pattern另外開出領域(domain)獨有的類別。
以下是參考Android Architecture Blueprint上MVVM架構的做法,以我們的需求為範例寫出來的實作程式碼:
在這個例子中,MVVM架構中各元件的職責分別是:
TemperatureDataSource
(Model):負責提供資料,不管資料是從本地、資料庫或API。MainActivity
(View):負責使用者介面的更新。TemperatureViewModel
(ViewModel):負責保存UI的狀態,將這些狀態使用LiveData
進行保存,同時也讓View來觀察狀態是否更新。
冷知識:在實作程式碼中是不是有看到_temperature
這個成員變數(或別名field, member variables, whatever😜)命名是底線開頭看起來醜醜的?我也看得不是很順眼阿~不過這其實是Kotlin Coding Convention與Kotlin style guide裡面Backing property的寫法喔。
來寫互動測試吧!
(註:InstantTaskExecutorRule
的功能大致上和RxSchedulerRule
相同,功用是用來告訴LiveData
立即去notify change給它的observer)
值得注意的是LiveData如果要被observe有兩種方法:
observe(LifecycleOwner owner, Observer observer)
一般不建議這個方法,因為需要在測試內帶入LifecycleOwner
這個component,這樣就得執行Android Test,而沒辦法進行執行速度最快的Local Test。observeForever(Observer observer)
✅
比較建議這個方法!因為不需要額外的dependency,只需要將Observer
mock起來,就可以進行測試。
寫測試還有一個好處是,當需求變更時,你可以很放心的改動邏輯,在不會改壞現有功能的情況下擴展新的功能。舉例來說,現在我們的溫度單位必須支援華氏與攝氏兩種單位:
在現有功能被測試保護的狀態下,我們可以很輕鬆的加入TemperatureUnit
這個class來進行重構,只要測試可以通過(綠燈亮起來!)就表示重構後的程式碼是相容於舊有需求的,我們可以在這前提下自由自在的優化程式碼,甚至擴充新的功能。