1. 程式人生 > >蘑菇街支付金融Android單元測試實踐

蘑菇街支付金融Android單元測試實踐

本文為『移動前線』群在4月23日的分享總結整理而成,轉載請註明來自『移動開發前線』公眾號。

嘉賓介紹

鄒勇(網名小創)蘑菇街支付金融資深安卓開發工程師。自畢業以來一直從事Android開發工作,先後工作於創新工廠、微策略以及蘑菇街。對單元測試和TDD情有獨鍾。

大家好,我是蘑菇街支付金融部門的鄒勇,花名叫小創。今天很高興跟大家分享一下安卓的單元測試在蘑菇街支付金融的實踐。下面,我們從為什麼開始。

為什麼要寫單元測試

首先要介紹為什麼蘑菇街支付金融這邊會採用單元測試的實踐。說起來比較巧,剛開始的時候,只是我一個人會寫單元測試。後來老闆們知道了,覺得這是件很有價值的事情,於是就叫我負責我們組的單元測試這件事情。就這樣慢慢的,單元測試這件事情就成了我們這邊的正常實踐了。再後來,在公司層面也開始有一定的推廣。

要說為什麼要寫單元測試的話,我相信大部分人都能承認、也能理解單元測試在保證程式碼質量,防止bug或儘早發現bug這方面的作用,這可能是大家覺得單元測試最大的作用。然而我覺得,除了這方面的作用,單元測試還能在很大程度上改善程式碼的設計,同時還能節約時間,讓人工作起來更自信、更開心,以及其他的一些好處。這些都是我的切身感受,我相信也是多數真正實踐過單元測試的人的切身感受,而不是為了宣傳這個東西而說的好聽的大話。

說到節約時間,大家可能就會好奇了,寫單元測試需要時間,維護單元測試程式碼也需要時間,應該更費時間才對啊?

這就是在開始分享之前,我想重點澄清的一點,那就是,單元測試本身其實不會佔用多少時間,相反,還會節約時間。只是:

  1. 學習如何做單元測試需要時間;

  2. 在一個沒有單元測試的專案中加入單元測試,需要一定的結構調整的時間,因為一個有單元測試跟沒有單元測試的專案,結構上還是有較大不同的。

打個比方,開車這件事情,需要很多時間嗎?我相信很少人會說開車這件事情需要很多時間,而是:

  1. 學習開車,需要一定的時間;

  2. 如果路面不平的話,那麼修路需要一定的時間。單元測試也是類似的情況。

那為什麼說單元測試可以節約時間呢?簡單說幾點:

  1. 如果沒有單元測試的話,就只能把app執行起來測試,這比執行一次單元測試要慢多了。

  2. 儘早發現bug,減少了debug和fixbug的時間。

  3. 重構的時候,大大減少手動驗證重構正確性的時間。

所以,我希望大家能去掉"沒時間寫單元測試"這個印象,如果工作上安排太緊,沒有時間學習如何做單元測試的話,可以自己私底下學,然後在慢慢應用到專案中。

單元測試簡單介紹

接下來介紹我們這邊是怎麼做安卓單元測試的。首先澄清一下概念,在安卓上面寫測試,有很多技術方案。有JUnit、Instrumentation test、Espresso、UiAutomator等等,還有第三方的Appium、Robotium、Calabash等等。我們現在講的是使用JUnit和其他的一些框架,寫可以在我們開發環境的JVM上面直接執行的單元測試,其他的幾種其實都不屬於單元測試,而是整合測試或者叫Functional test等等。這兩者明顯的不同是,前者可以直接在開發用的電腦,或者是CI上面的JVM上執行,而且可以只執行那麼一小部分程式碼,速度非常快。而後者必須要有模擬器或真機,把整個project打包成一個app,然後上傳到模擬器或真機上,再執行相關的程式碼,速度相對來說慢很多。

單元測試的定義相信大家都知道,就是為我們寫的某一個程式碼單元(比如一個方法)寫的測試程式碼。一個單元測試大概可以分為三個部分:

  1. setup:即new 出待測試的類,設定一些前提條件

  2. 執行動作:即呼叫被測類的被測方法,並獲取返回結果

  3. 驗證結果:驗證獲取的結果跟預期的結果是一樣的

然而一個類的方法分兩種,一種是有返回值的方法。一種是沒有返回值的方法,即void方法。對於有返回值的方法,固然測試起來是很容易的,但是對於沒有返回值的方法,該怎麼測試呢?這裡的關鍵是,怎麼樣獲取這個方法的“返回結果”?

這裡舉一個例子來說明一下,順便澄清一個十分常見的誤解。比如說有一個Activity,管他叫DataActivity,它有一個public void loadData()方法, 會去呼叫底層的DataModel類,非同步的執行一些網路請求。當網路請求返回以後,更新使用者介面。

這裡的loadData()方法是void的,它該怎麼測試呢?一個最直接的反應可能是,呼叫loadData()方法(當然,實際可能是通過其他事件觸發),然後一段時間後,驗證介面得到了更新。然而這種方法是錯的,這種測試叫整合測試,而不是單元測試。因為它涉及到很多個方面,它涉及到DataModel、網路伺服器,以及網路返回正確時,DataActivity內部的處理,等等。整合測試固然有它的必要性,但不是我們應該最關注的地方,也不是最有價值的地方。我們應該最關注的是單元測試。關於這一點,有一個Test Pyramid的理論:

Test Pyramid理論基本大意是,單元測試是基礎,是我們應該花絕大多數時間去寫的部分,而整合測試等應該是冰山上面能看見的那一小部分。

那麼對於這個case,正確的單元測試方法,應該是去驗證loadData()方法呼叫了DataModel的某個請求資料的方法,同時傳遞的引數是正確的。“呼叫了DataModel的方法,同時引數是。。。” 這個才是loadData()這個方法的“返回結果”。

Mock的概念以及Mockito框架

要驗證某個物件的某個方法得到呼叫了,就涉及到mock的使用。這裡對mock的概念做個簡單介紹,以免很多同學不熟悉,mock就是建立一個虛假的、模擬的物件。在測試環境下,用來替換掉真實的物件。這樣就能達到兩個目的:

  1. 可以隨時指定mock物件的某個方法返回什麼樣的值,或執行什麼樣的動作。

  2. 可以驗證mock物件的某個方法有沒有得到呼叫,或者是呼叫了多少次,引數是什麼等等。

要使用mock,一般需要使用mock框架,目前安卓最常用的有兩個,MockitoJMockit。兩者的區別是,前者不能mock static method和final class、final method,後者可以。我們依然採用的是Mockito,原因說起來慚愧,是因為剛開始並不知道JMockit這個東西,後來查了一些資料,看過很多對比Mockito和JMockit的文章,貌似大部分還是很看好JMockit的,只是有一個問題,那就是跟robolectric的結合也有一些bug,同時使用姿勢跟Mockito有較大的不同,因此一直沒有抽時間去實踐過。這個希望以後能夠做進一步的調查,到時候在給大家分享一下使用感受。

但是使用Mockito,就有一個問題,那就是static method和final class、final method沒有辦法mock,對於這點如何解決,我們稍後會介紹到。

在測試環境中使用mock:依賴注入

接下來的一個問題就是,如何在測試環境下,把DataModel換成mock的物件,而正式程式碼中,DataModel又是正常的物件呢?

這個問題也有兩種解決方案,一是使用專門的testing product flavor;二是使用依賴注入。第一種方案就是用一個專門的product flavor來做testing,在這個testing flavor裡面,裡面把需要mock的類寫一份mock的implementation,然後通過factory提供給client,這個factory的介面在testing flavor和正式的flavor裡面是一樣的,在跑testing的時候,專門使用這個testing flavor,這樣通過factory得到的就是mock的類。這種情況看起來很簡單,但其實很不靈活,因為只有一種mock實現;此外,程式碼會變得很醜陋,因為你需要為每一個dependency提供一個factory,會覺得很刻意;再者,多了一個flavor,很多gradle任務都會變得很慢。關於這種方案,可以參考這個視訊(https://www.youtube.com/watch?v=vdasFFfXKOY)。

因此,我們用的是第二種,依賴注入。先簡單介紹一下依賴注入這個模式,他的基本理念是,某一個類(比如說DataActivity),用到的內部物件(比如說DataModel)的建立過程不在DataActivity內部去new,而是由外部去建立好DataModel的例項,然後通過某種方式set給DataActivity。這種模式應用是非常廣泛的,尤其是在測試的時候。為了更方便的做依賴注入,如今有很多框架專門做這件事情,比如RoboGuiceDaggerDagger2等等。我們用的是Dagger2,理由很簡單,這是目前最好用的DI框架。

關於Dagger2的文章,之前我們群裡也分享了不少,但是好像我並沒有看到講述沒有關於如何在測試環境下使用Dagger2的文章,這個還是略感遺憾的。離開單元測試,使用依賴注入就少了很有說服力的一個理由。

那麼這裡我就介紹一下,怎麼樣把Dagger2應用到單元測試中。熟悉dagger2的童靴可能知道,Dagger2裡面最關鍵的有兩個概念,ModuleComponent。Module是負責生成諸如DataModel這樣被別人(比如DataActivity)使用的類的地方。用術語的話,被別人使用的類DataModel叫Dependency,使用到了別的類的類DataActivity叫Client。而Component則是供Client使用Dependency的統一介面。也就是說,DataActivity通過Component,來得到一份DataModel的例項。

現在,關鍵的地方來了,Component本身是不生產dependency的,它只是搬運工而已,真正生產dependency的地方在Module。所以,建立Component需要用到Module,不同的Module生產出不同的dependency。在正式程式碼裡面,我們使用正常的Module,生產正常的DataModel。而在測試環境中,我們寫一個TestingModule,讓它繼承正常的Module,然後override掉生產DataModel的方法,讓它生產mock的DataModel。在跑單元測試的時候,使用這個TestingModule來建立Component,這樣的話,DataActivity通過Component得到的DataModel物件就是mock出來的DataModel物件。

使用這種方式,所有production code都不用專門為testing增加任何多餘的程式碼,同時還能得到依賴注入的其他好處。

Robolectric:解決Android單元測試最大的痛點

接下來講講Android單元測試最大的痛點,那就是JVM上面執行純JUnit單元測試時是不能使用Android相關的類的,因為我們開發用到的安卓環境是沒有實現的,裡面只定義了一些介面,所有方法的實現都是throw new RuntimeException("stub");,如果我們單元測試程式碼裡面用到了安卓相關的程式碼的話,那麼執行時就會遇到RuntimeException("Stub")。

要解決這個問題,一般來說有三種方案:

  1. 使用Android提供的Instrumentation系統,將單元測試程式碼執行在模擬器或者是真機上。

  2. 用一定的架構,比如MVP等等,將安卓相關的程式碼隔離開了,中間的Presenter或Model是存java實現的,可以在JVM上面測試。View或其他android相關的程式碼則不測。

  3. 使用Robolectric框架,這個框架基本可以理解為在JVM上面實現了一套安卓的模擬環境,同時給安卓相關的類增加了其他一些增強的功能,以方便做單元測試,使用這個框架,我們就可以在JVM上面跑單元測試的時候,就可以使用安卓相關的類了。

第一種方案能work,但是速度非常慢,因為每次執行一次單元測試,都需要將整個專案打包成apk,上傳到模擬器或真機上,就跟運行了一次app似得,這個顯然不是單元測試該有的速度,更無法做TDD。這種方案首先被否決。

剛開始,我們採用的是Robolectric,原因有兩個:

  1. 我們專案當時還沒有比較清楚的架構,android跟純java程式碼的隔離沒有做好;

  2. 很多安卓相關的程式碼,還是需要測試的,比如說自定義View等等。

然而慢慢的,我們的態度從擁抱Robolectric,到儘量不用它,儘量使用純java程式碼去實現。可能大家覺得安卓相關的程式碼會很多,而純java的很少,然而慢慢的你會發現,其實不是這樣的,純java的程式碼其實真不少,而且往往是核心的邏輯所在。之所以儘量不用Robolectric,是因為Robolectric雖然相對於Instrumentation testing來說快多了。但畢竟他也需要merge一些資源,build出來一個模擬的app,因此相對於純java和JUnit來說,這個速度依然是很慢的。

用具體的數字來對比說明:

  • 執行Instrumentation testing:幾十秒,取決於app的大小

  • Robolectric:10秒左右

  • JUnit:幾秒鐘之內

當然,雖然執行一次Robolectric在10秒左右,但是對比執行一次app,還是要快太多。因此,剛開始的時候,從Robolectric開始完全是OK的。

以上就是現在我們這邊單元測試用到的幾個基本技術:JUnit4 + Mockito + Dagger2 + Robolectric。基本來說,並沒有什麼黑科技,都是業界標準。

一個具體的案例

接下來,我通過一個具體的案例,跟大家介紹一下,我們這邊的一個app,具體是怎麼單測的。

這裡是我們收銀臺介面的樣子:

假設Activity名字為CheckoutActivity,當它啟動的時候,CheckoutActivity會去調一個CheckoutModel的loadCheckoutData()方法,這個方法又會去調更底層的一個封裝了使用者認證等資訊的網路請求Api類(mApi)的get方法,同時傳給這個Api類一個callback。這個callback的做的事情是將結果通過Otto Bus(mBus) post出去。CheckoutActivity裡面Subscribe了這個Event(方法名是onCheckoutDataLoaded()),然後根據Event的值相應的顯示資料或錯誤資訊。

程式碼簡寫如下:

這裡,CheckoutActivity裡面的mCheckoutModel、CheckoutModel裡面的mApi、CheckoutModel裡面的mBus,都是通過Dagger2注入進去的。在做單元測試的時候,這些都是mock。

對於這個流程,我們做了如下的單元測試:

  • CheckoutActivity啟動單元測試:通過Robolectric提供的方法,啟動一個Activity。驗證裡面的mCheckoutModel的loadCheckoutData()方法得到了呼叫,同時引數(訂單ID等)是對的。

  • CheckoutModel的loadCheckoutData單元測試1:呼叫CheckoutModel的loadCheckoutData()方法,驗證裡面的mApi對應的get方法得到了呼叫,同時引數是對的。

  • CheckoutModel的loadCheckoutData單元測試2:mock Api類,指定當它的get方法在收到某些呼叫的時候,直接呼叫傳入的callback的onSuccess方法,然後呼叫CheckoutModel的loadCheckoutData()方法,驗證Otto bus的post方法得到了呼叫,並且引數是對的。

  • CheckoutModel的loadCheckoutData單元測試3:mock api類,指定當它的get方法在收到某些呼叫的時候,直接呼叫傳入的callback的onFailure方法,然後呼叫CheckoutModel的loadCheckoutData()方法,驗證Otto bus的post方法得到了呼叫,並且引數是對的。

  • CheckoutActivity的onCheckoutDataLoaded單元測試1:啟動一個CheckoutActivity,呼叫他的onCheckoutDataLoaded(),傳入含有正確資料的Event,驗證相應的資料view顯示出來了

  • CheckoutActivity的onCheckoutDataLoaded單元測試2:啟動一個CheckoutActivity,呼叫他的onCheckoutDataLoaded(),傳入含有錯誤資訊的Event,驗證相應的錯誤提示view顯示出來了。

這裡需要說明的一點是,上面的每一個測試,都是獨立進行的,不是說下面的單元測試依賴於上面的。或者說必須先做上面的,再做下面的。

這部分較為詳細的程式碼放在github(https://github.com/ChrisZou/android-unit-testing-tutorial)上,groupshare這個package裡面。

其他的問題

以上就是我們這邊做單元測試用到的技術,以及一個基本流程,下面聊聊其他的幾個問題。

哪些東西需要測試呢?

  1. 所有的Model、Presenter/ViewModel、Api、Utils等類的public方法

  2. Data類除了getter、setter、toString、hashCode等一般自動生成的方法之外的邏輯部分

  3. 自定義View的功能:比如set data以後,text有沒有顯示出來等等,簡單的互動,比如click事件,負責的互動一般不測,比如touch、滑動事件等等。

  4. Activity的主要功能:比如view是不是存在、顯示資料、錯誤資訊、簡單的點選事件等。比較複雜的使用者互動比如onTouch,以及view的樣式、位置等等可以不測。因為不好測。

CI和code coverage: Jacoco

要把單元測試正式化,CI是非常重要的一步,我們有一個執行Jenkins的CI server,每次開發者push程式碼到master branch的時候,會執行一次單元測試的gradle task,同時使用Jacoco做code coverage。

這裡有個坑要特別注意,那就是專案裡面的gradle Jacoco外掛和Jenkins的Jacoco外掛的相容性問題。我們用的gradle Jacoco外掛是7.1,更高版本的好像有問題。然後對應的Jenkins的Jacoco外掛需要1.0.19或更低版本的,更高版本的jenkins plugin不支援低版本的gradle Jacoco專案版本。實際上,這點在Jenkins的Jacoco外掛首頁就有說明:

(點選放大影象)

但是我當時沒注意,所以覆蓋率資料一直出不來,折騰了好一會,最後還是在同事的幫助下找到問題了。

遇到的坑,以及好的practice建議

接下來講講我們遇到的一些坑,以及一些好的practice建議。

1. Native libary

無論是純JUnit還是Robolectric,都不支援load native library,會報UnsatisfiedLinkError的錯。所以如果你的被測程式碼裡面用到了native lib,那麼可能需要給System.loadLibrary加上try catch。

如果是被測程式碼用到的第三方lib,而裡面用到了native lib的話,一般有兩種解決辦法,一種是將用到native lib的第三方類外面自己在包一層,然後在測試的情況下mock掉。第二種是用Robolectric,給那個類建立一個shadow class。

第一種方法的好處是可以在測試的時候隨時改變這個類的返回值或行為,缺點是需要另外建立一個wrapper類,會有點繁瑣。第二種方式不能隨時改變這個類的行為,但是寫起來非常簡單。所以,看自己的需要,選擇相應的方法。

這兩種方法,也是解決static method, final class/method不能mock的主要方式。

2. 儘量寫出易於測試的程式碼

static method、直接new object、singleton、Global state等等這些都是一些不利於測試的程式碼方式,應該儘量避免,用依賴注入來代替這些方式。

3. 不要重複你的unit test

比如說你使用了一個builder模式來建立了一個類,這個builder有一個validator,來validate一些引數情況。那麼這種情況,builder跟validator分開測,用各種正確的錯誤的引數情況去測試validator,然後測builder的時候,就不用遍歷各種有效的跟無效的引數去測試了。

因為如果這樣的話,到時候Validator的邏輯改了,那麼針對Validator的測試跟針對Builder的測試都要修改,這個其實是重複的。這裡只需要測試這個builder裡面有一個Validator就好了。

4. 公共的單元測試library

如果你們公司也是元件化開發的話,抽出一個公共的單元測試類庫來做單元測試,裡面可以放一些公共的helper、utils、rules等等,這個可以極大的提高寫單元測試的速度。

5. 把安卓裡面的“純java”程式碼copy一份到自己的專案裡面

安卓裡面有些類其實跟安卓沒太大關係的,比如說TextUtils、Color等等,這些類完全可以把程式碼copy出來,放到自己的專案裡面,然後其他地方就用這個類,這樣也能部分擺脫android的依賴,使用JUnit而不是Robolectric,提高執行test的速度。

6. 充分發揮JUnit Rule的作用

JUnit Rule是個很強大的工具,然而知道的人卻不多。它的基本作用是,讓你在執行某個測試方法前後,可以做一些事情。如果你的好幾個測試類裡面有很多的共同的setup、teardown工作,你可能會傾向於使用繼承,結合@Before、@After來減少duplication,這裡更建議大家使用JUnit Rule來實現這個目的,而不是用繼承,這樣可以有更大的靈活性。

比如,為了方便測試Activity的method,我們有一個ActivityRule,在跑一個測試方法之會啟動target Activity,然後跑完以後自動finish這個activity。

其中一個比較有趣的用JUnit Rule實現的功能,是實現類似於BDD測試框架的命名方式。做單元測試的時候,你經常需要為同一個方法寫好幾個測試方法,每個測試方法測試不同的點。為了讓命名更具可讀性,我們往往會把名字寫的很長,在這種情況下,如果用駝峰命名的話,需要不斷切換大小寫,寫起來麻煩,可讀性也不高。如果用下劃線的話,寫起來也很麻煩。如果你使用過BDD的一些框架(比如RSpecCucumberJasmine等),你就會異常懷念那種“命名”方式。如果你沒用過的話,那種“命名”方式大概是這樣的:

這裡的關鍵是,當測試方法失敗的時候,這個字串是要能被加到錯誤資訊裡面的。我們做了個JUnit Rule來達到這個效果。做法是結合一個自定義的annotation,這個annotation接收一個String,來描述這個測試方法的測試目的。在Rule裡面將這個annotation讀出來,如果測試沒通過的話,把這個描述性的String加到輸出的error message裡面。這樣在批量執行的時候,一看就知道沒通過的測試是測什麼東西的。而測試方法的命名則可以比較隨意。
達到的效果如下:

如果執行失敗,得到如下的結果

關於JUnit Rule的使用,大家可以自行google一下,也不難。

7. 善於利用AndroidStudio來加快你寫測試的速度

AndroidStudio有很多feature可以幫助我們更快的寫程式碼,比如code generation和live template。這點對於寫正式程式碼也適用,不過對於寫測試程式碼來說,效果更為突出。因為大部分測試程式碼的結構、風格都是類似的,在這裡live template能起非常大的作用。此外,如果你先寫測試,可以直接寫一些還不存在的Class或method,然後alt+enter讓AndroidStudio自動幫你生成。

8. 不要追求完美

剛開始的時候,不用追求測試程式碼的質量,也不用追求完美,如果有些地方不好寫測試,可以先放放,以後再來補,有部分測試總比沒有測試好。Martin Fowler說過

Imperfect tests, run frequently, are much better than perfect tests that are never written at all.

然而等你熟悉寫測試的方法以後,強烈建議先寫測試!因為如果你先寫了正式程式碼,那你對這寫程式碼是如何work的已經有一個印象了,因此你往往會寫出能順利通過的測試,而忽略一些會讓測試不通過的情況。如果先寫測試,則能考慮得更全面。

9. 未來的打算

使用Groovy和RoboSpock或者是Kotlin和Spek,真正實現BDD,這是很可能的事情,只是目前我們這邊還沒太多那方面的實踐,因此就不說太多了。以後有一定實踐了,到時候可以再更大家交流。

QA環節

Q:如何測試介面互動?如點選拖動等。

A:Robolectric提供了非常豐富的測試互動的方式,比如findViewById(id).performClick()。基本上,使用Robolectric,你可以像正常寫安卓程式碼那樣寫測試程式碼。甚至正常情況下沒有的方法,Robolectric也提供了。

Q:我也是後來才接觸程式碼測試的,然後開始喜歡上寫程式碼測試,但當嘗試為以前的程式碼寫程式碼測試的時候,發現以前的結構很難寫程式碼測試,請問你們也有遇到這種情況麼?如何解決。

A:這的確是比較頭疼的問題,建議可以看看《Working Effective With Legacy Code》一般來說就是挑選一個比較好下手的地方,做好隔離寫好測試,在重構。那本書裡面提出了很多簡單除暴的方式,比如把一個方法或變數從private改成public等等。

Q:自繪控制元件一般怎麼去做自動化測試?

A: 自定義控制元件一般只測他的功能性的部分,樣式、動畫這樣的一般不測。

測試方式基本就是把這個控制元件new 出來,然後呼叫它的public 方法,驗證它的text是不是正確等等。或者是相應的事件有沒有觸發,這個藉助Robolectric可以做到。

Q:業務測試資料,是自己本地寫的邏輯,還是結合伺服器的真實邏輯?

A:對於單元測試來說,一般是自己mock伺服器的返回結果,因為伺服器返回結果是不是正確的,其實不是我們應該測的情況,而是伺服器應該測的情況,我們要測的,是伺服器返回正確的結果我們就顯示正確的結果,伺服器返回錯誤的結果,我們就顯示錯誤的返回資訊。

Q:MVP的情況下view和presenter的回撥函式需要做測試嗎,如果需要怎麼做?

A:要測,把presenter new出來,直接呼叫它的那個方法就是了。

Q:對於依賴環境的測試,比如有無網路,不同的網路測試型別,不同的網路型別,網路超時等,這種怎麼去做單元測試比較好?在比如測試試寫檔案的方法,怎麼去構造剩餘空間不足、空間足夠的環境?

A:這些情況需要藉助系統的api(比如NetworkManager),去判斷情況,這種情況可以把這些系統的api mock掉,指定讓他返回你想要指定的結果。

Q:為啥方法名不是駝峰命名法?

相關推薦

蘑菇支付金融Android單元測試實踐

本文為『移動前線』群在4月23日的分享總結整理而成,轉載請註明來自『移動開發前線』公眾號。 嘉賓介紹 鄒勇(網名小創)蘑菇街支付金融資深安卓開發工程師。自畢業以來一直從事Android開發工作,先後工作於創新工廠、微策略以及蘑菇街。對單元測試和TDD情有獨鍾。

Android單元測試實踐

為什麼要引入單元測試 一般來說我們都不會寫單元測試,為什麼呢?因為要寫多餘的程式碼,而且還要進行一些學習,入門有些門檻,所以一般在工程中都不會寫單元測試。那麼為什麼我決定要寫單元測試。因為兩個條件 我很懶:我每次改完都很懶測試 我很慫:我要是不測試,沒有一次通過的信心,於是我還

通過JUnit進行Android單元測試

2個 nvi frame oncreate protected [] 命令 lib 是我 要了解android單元測試,首先必須了解junit 什麽是 JUnit ? JUnit是采用測試驅動開發的方式,也就是說在開發前先寫好測試代碼,主要用來說明被測試的代碼會被如

MVC與單元測試實踐之健身網站(一)-項目概述

dto 使用 基礎 資料 ima size 描述 健身 nunit 前不久剛剛通過租房網站的開發學習了MVC,並隨後學習了單元測試相關的基礎,現在開始健身網站的開發,該項目將結合MVC與單元測試,在開發實踐過程中,趁熱打鐵,鞏固並運用之前的內容。 一 健身網站功能描述

太白---落燕紛飛第一重 Android單元測試Instrumentation和irobotium

tom 先來 otto 重現 size sim 個人 思想 pack PS:叫太白---落燕紛飛純粹好玩(天涯明月遊戲畫面感,打擊感,碰撞盡管做的不盡人意,可是太白這個職業還是不錯,用作開頭,,做個旁白而已)。 這裏的單元測試不管是instrumenta

MVC與單元測試實踐之健身網站(六)-計劃的添加與重置

兼容 跳轉 需要 以及 str 額外 休息 保存 bsp 健身計劃需要使用者自己定制,沒有現成的內容可供選擇。本篇就是關於健身計劃的添加與重置功能的一部分。 一 功能描述 a) 關於計劃的定制,決定以周期的方式,比如有人會以一周為周期,然後安排每周的1、3、5進行鍛煉。系統

MVC與單元測試實踐之健身網站(七)-添加計劃

感覺 同步 語句 -s mil none tro c# 技術分享 ?計劃的制定涉及到周期-動作包-動作的關聯操作,在上一篇<計劃的添加與重置>完成了周期的設置、動作包的添加,現在要完成的是動作的添加操作。 一 具體功能 a) 在選定了一個大周期具有的天數後,

MVC與單元測試實踐之健身網站(完)-備案與部署

網站 img 指標 身體 根據 直觀 健身 自己的 tts 主頁-http://www.zhixin9001.cn/Home/Introduce GitHub- https://github.com/zhixin9001/Fitness 這是關於Fit網站的最後一篇,這

android單元測試框架Mockito使用

null 修改 分享 log hone 技術 pro 我們 ext 單元測試,早些年時常聽到這個概念,真的有去做的確實少,基本都是自己功能上的測試,開發完測試跑一邊沒啥問題就發布了。這幾天花了點心思看了下MockIto框架,記錄博文。 MockIto官網文檔在https:

深入淺出Android單元測試(一):單元測試基礎

想學習單元測試無從下手,本文對以最易懂的方式介紹單元測試。 若有錯漏,煩請斧正。轉載請註明出處。歡迎關注程式引力 作者:程式引力 | 謝一 (Evan Xie) 郵箱:[email protected] 軟體測試作為軟體質量的保障,有著十分重要的意義。按照不同

android 單元測試cmd 命令集

對app進行單元測試時,或使用robotium進行黑盒測試時,需要把測試apk安裝到模擬器或者android真機上,然後用命令去驅動測試 1.執行測試程式命令-執行測試工程中所有test方法: >adb shell am instrument -w 測試程式packageName/an

Android單元測試(一):JUnit框架的使用

1.前言 網上有許多關於單元測試的好處,這裡我就不去說了。我寫單元測試的理由很簡單粗暴,就是圖一個方便。試想一下這個場景:我們在寫一個新功能,每寫一部分,我們就安裝到手機上檢視一下,這個過程中你要點選到對應的頁面,做對應的操作,最後才能反饋給你結果。如果達到了預

Android單元測試(五):網路介面測試

溫馨提示:如果你不太熟悉單元測試,可以先看下之前四篇基礎框架使用。便於你更好的理解下面的內容。 在平日的開發中,我們用後臺寫好給我們介面去獲取資料。雖然我們有一些請求介面的工具,可以快速的拿到返回資料。但是在一些異常情況的處理上就不太方便了。我列出以下

Android單元測試(6):使用dagger2來做依賴注入

注: 1. 程式碼中的 //<= 表示新加的、修改的等需要重點關注的程式碼 2. Class#method表示一個類的instance method,比如 LoginPresenter#login 表示 LoginPresenter的login(非靜態)方法。 問題

Android單元測試中AndroidJUnit4獲取context

在AndroidJUnit4直接通過getContext()獲取到的context並不是當前APP的context,而是instrumentation的context,應使用以下方法來獲取context。 InstrumentationRegistry.getInstrum

基於jenkins的自動化單元測試實踐

一、 單元測試並生成報告 1、maven外掛 <reporting> <plugins> <plugin> <groupId>org.apache.

android 單元測試脫坑

說明 本文描述的是Junit4,筆者是android 兩年的搬運工,寫專案很少寫單元測試。 但有時候測一段邏輯或者網路請求需要把工程跑一遍,再操作一遍。 接觸單元測試才認識到它的強大,它能省去很多麻煩和時間。 我們雖然不是測試,也應該知道怎麼去簡單使用它

Android單元測試:使用本地資料測試Retrofit

簡述 在日常專案開發中,基本沒有什麼機會用到Kotlin,幾個月前學習的語法,基本上都忘光了,於是自己強迫自己在寫Demo中使用Kotlin,同時,在目前開發的專案中開了一個測試分支,用來補全之前沒有寫的測試程式碼。 筆者的Android單元測試相關係列

二.Android單元測試 Mockito的更多用法

 相對於上篇文章,這篇介紹了更多mockito的用法,對照著MeetingPresenterImp.java和MeetingPresenterImpTest.java大家可以看看Android單元測試用例怎麼寫. public class MeetingP

Android單元測試(九):查漏補缺篇

最近抽時間檢查了一下年前有關單元測試的八篇部落格,查漏補缺了一下。後面如果有更多關於單元測試的心得收穫,也會繼續補充。 1.AssertJ 在Android單元測試(一):JUnit框架的使用中,我們介紹瞭如何使用JUnit來進行斷言。不多說實話