Android中的互動測試(Interaction Testing in Android)第三部曲:MVVM架構下的互動測試

Carter Chen
4 min readSep 16, 2019

--

Photo by Annette Sousa on Unsplash

前情提要

這是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 ConventionKotlin style guide裡面Backing property的寫法喔。

來寫互動測試吧!

(註:InstantTaskExecutorRule的功能大致上和RxSchedulerRule
相同,功用是用來告訴LiveData 立即去notify change給它的observer)

值得注意的是LiveData如果要被observe有兩種方法:

  1. observe(LifecycleOwner owner, Observer observer)
    一般不建議這個方法,因為需要在測試內帶入LifecycleOwner 這個component,這樣就得執行Android Test,而沒辦法進行執行速度最快的Local Test。
  2. observeForever(Observer observer)
    比較建議這個方法!因為不需要額外的dependency,只需要將Observer mock起來,就可以進行測試。

寫測試還有一個好處是,當需求變更時,你可以很放心的改動邏輯,在不會改壞現有功能的情況下擴展新的功能。舉例來說,現在我們的溫度單位必須支援華氏與攝氏兩種單位:

在現有功能被測試保護的狀態下,我們可以很輕鬆的加入TemperatureUnit這個class來進行重構,只要測試可以通過(綠燈亮起來!)就表示重構後的程式碼是相容於舊有需求的,我們可以在這前提下自由自在的優化程式碼,甚至擴充新的功能。

--

--

No responses yet