3.1 Android單元測試難點
在Android應用程序里寫單元測試時,剛開始往往會有無從下手的感覺。他既有處理UI邏輯的代碼汰现,也有處理業(yè)務邏輯的代碼,總感覺一團亂麻叔壤。根據個人的經驗總結起來瞎饲,本人覺得主要難點有以下幾條:
- Activity類充當了god class(上帝類),它接管了所有的職責炼绘,各種業(yè)務邏輯錯綜復雜的穿插在一起嗅战。業(yè)務邏輯之間沒有一個清晰的邊界,也就無法劃分出“單元”俺亮。
- 針對UI層面的單元測試驮捍,業(yè)界沒有統(tǒng)一的標準,不知該如何下手脚曾。
- Android默認的測試框架东且,必須運行在Android環(huán)境上,而這樣會導致每次寫單元測試時斟珊,都需要打包運行,才能進行測試富纸。如果你的項目工程很大囤踩,打包的時間會很長,這樣為了跑一個單元測試得花費老半天時間晓褪。
- 我們來測試某一個方法時堵漱,有時會發(fā)現,這個方法里某個地方會依賴一個很重的對象來處理某個業(yè)務邏輯涣仿,而這個重對象的構造確很復雜勤庐,這樣也會造成寫單元測試的困難示惊。
總的說來,造成單元測試很難寫的原因:一方面是程序架構的問題愉镰,業(yè)務邏輯分層不清晰米罚,職責不單一;另一方面是沒有一個好的測試框架丈探,有好的工具才會事半功倍录择。
3.2 如何解決單元測試難點
針對這些問題,我們一一來分析碗降,該采用什么樣的架構設計隘竭,以及采用什么樣的測試框架,能解決我們寫單元測試的難點讼渊。
- 以前的Android應用程序动看,都是采用傳統(tǒng)的MVC開發(fā)模式。MVC模式共分為3層:Model層爪幻、Controller層菱皆、View層,三層之間代碼通常會耦合嚴重笔咽,彼此之間存在嚴重的依賴關系搔预,這其實違反了軟件設計高內聚、低耦合的原則叶组。我們期待的是能夠對每一層都能進行單獨測試拯田,層與層之間沒有那么多的彼此依賴。由此甩十,在MVC的基礎之上演化出了MVP設計模式(不懂的自行搜索學習)船庇,UI與業(yè)務邏輯完全隔離開來,這樣就可以單獨針對P層來測試侣监,也可單獨針對Model層來測試屿愚。
- UI層的單元測試,現在谷歌提供了一個默認的測試框架Espresso+AndroidJUnitRunner顶猜,應該說官方提供的這個測試框架一定程度上解決了UI測試難的問題沪曙。
- 打包慢是大家都會碰到的問題,我們期望的是有這么一個測試環(huán)境:當我們寫好單元測試代碼姓蜂,能不能直接運行在JVM環(huán)境上按厘,就像運行一個java類里面的main方法一樣那么簡單,不用每次都要打包那么麻煩而且緩慢钱慢。很早就有了JUnit這么一個測試框架逮京,它只能運行純java代碼,但是我們的代碼里面會用到很多Android SDK的東西束莫,這樣JUnit就不能完全滿足我們的需求了懒棉。幸運的是草描,我們有了Robolectric單元測試框架,它實現了一套JVM能運行的Android代碼策严,一定程度上做到了脫離Android環(huán)境進行測試穗慕。
- 單元測試是針對某個方法來寫的,如果這個方法里依賴了一個很重的對象(構造這個對象很復雜)享钞,那我們該怎么辦呢揍诽。同樣幸運的是,我們有Mockito這個測試神器栗竖。我們可以使用Mockito這么一個測試框架暑脆,對這些及其復雜的對象,mock一個出來狐肢,mock出來的對象具備了與原來對象一模一樣的功能添吗,這樣就解決了這個問題。
3.3 測試方案
最終我選擇的測試方案如下圖所示:
Presenter層僅僅處理業(yè)務邏輯份名,不需要處理UI等碟联,所以我選擇了直接運行在JVM環(huán)境上的框架;View層都是UI相關的東西僵腺,這個沒的選擇鲤孵;Model層有2種選擇,一種類似于數據庫存儲辰如、SharePreference數據讀取普监,它必須運行在Android環(huán)境上才方便測試,一種類似于Restfull Api接口請求之類的琉兜,它在JVM環(huán)境上是可以直接運行的凯正,所以這里我選擇了2種框架,具體根據實際情況來選擇豌蟋。
3.4 小結
本文先總結了Android單元測試的幾個難點廊散,接著針對這幾個難點一一分析怎么去解決它們,最后確定了Android單元測試的整體測試方案梧疲,主要是不同情況下不同單元測試框架的選擇允睹。
系列文章:
Android單元測試(一):前言
Android單元測試(二):什么是單元測試
Android單元測試(三):測試難點及方案選擇
Android單元測試(四):JUnit介紹
Android單元測試(五):JUnit進階
Android單元測試(六):Mockito學習
Android單元測試(七):Robolectric介紹
Android單元測試(八):怎樣測試異步代碼